【问题标题】:Mac L&F problems: Differing behavior of JTextField.requestFocus()Mac L&F 问题:JTextField.requestFocus() 的不同行为
【发布时间】:2009-10-09 12:27:53
【问题描述】:

我的 JTextField.requestFocus() 行为在 Mac OS X 上似乎有所不同。

这是我的情况:我有一个包含 JList 和 JTextField 的对话框。用户应该在文本字段中编写一个布尔表达式,该列表包含可能在表达式中输入的所有变量的名称。因为希望用户在单击列表中的变量后继续输入表达式,所以程序调用 JTextField.requestFocus() 很有帮助。这样,您可以例如从列表中单击“pvalue”,然后键入“

这一切在我的开发机器 (Linux) 上运行良好,但我收到了一个 Mac 用户的错误报告,点击列表实际上会选择文本字段中的所有文本,因此很容易意外覆盖之​​前输入的内容。

我怀疑这是 Mac 外观的问题,经过一番搜索,似乎确实有一个 Mac 外观的“Quaqua.TextComponent.autoSelect”属性似乎与这个问题:http://www.randelshofer.ch/quaqua/guide/jtextcomponent.html

我的一般问题是:

  • 您能建议解决此问题的方法吗?

如果范围太广,回答​​这些子问题已经很有帮助了:

  • 可能的解决方案是更改属性“Quaqua.TextComponent.autoSelect”。我怎么做?
  • 我什至不确定“Quaqua”是什么。它看起来像是一个定制的外观和感觉。 Mac OS X 的默认外观是什么?是否有类似于 Quaqua.TextComponent.autoSelect 的属性?
  • 是否可以仅针对单个组件实例调整外观?如果有,怎么做?
  • 是否可以在我的 Linux 开发机器上设置 Mac 的外观和感觉,以便我可以真正确认这个错误(以上所有内容都是基于预感和怀疑)?如果有,怎么做?

【问题讨论】:

    标签: java macos look-and-feel jtextfield


    【解决方案1】:

    似乎这是 Mac OS 的错误。 JTextField 在通过键盘选项卡循环获得焦点时选择它们的内容。如果插入点在文本中间,则插入点会保留,不会选中整个文本。

    作为一种解决方法,您可以使用以下方法覆盖此行为,它对我来说很好:

    textfield.setCaret(new DefaultCaret()).

    更多详情可以参考thisthis

    【讨论】:

    • 哇,这个简单的调用解决了它!我希望有一个比重新定位光标更简单的解决方案,就是这样。谢谢。
    【解决方案2】:

    要修改默认行为,您可以在初始化 UI 组件之前将系统属性设置为 false:System.setProperty("Quaqua.TextComponent.autoSelect", "false"); 要修改单个组件,您可以使用 JTextField#putClientProperty("Quaqua.TextComponent.autoSelect", Boolean.FALSE);

    您可以在此处找到其他 MacOS L&F 特定属性:

    Quaqua Look & Feel - User Guide

    【讨论】:

    • 这很有帮助,但看起来 Quaqua 是一种自定义外观,不一定是我的用户正在使用的。
    • 是的,它是默认 MacOS L&F 的扩展,不幸的是,它也改变了组件的行为(例如,选择焦点上的 TextFields 的内容)并且不仅修改了实际的 L&F。我知道你很难在你的应用程序中处理所有这些,但你至少可以建议 Quaqua 的用户在启动应用程序时从外部设置系统属性(-DQuaqua.TextComponent.autoSelect=false)。跨度>
    【解决方案3】:

    一种解决方法可能是(我还没有测试过)使插入变量名的JList 无法聚焦。这样,当您单击列表中的项目时,焦点将保留在文本字段中。我建议在JList 上使用setRequestEnabled(false),这样如果您选择它们​​,它们仍然可以聚焦,但是用鼠标单击它们不会聚焦它们。

    【讨论】:

      【解决方案4】:

      抱歉补充一个老问题,不过我刚碰到这个问题,用了下面的代码,看起来比上一个例子完整一点:

      // JTextField linkedText
      final int
        startBefore = linkedText.getSelectionStart(),
        endBefore = linkedText.getSelectionEnd();
      linkedText.requestFocus(); // this was the original code line!
      SwingUtilities.invokeLater(new Runnable()
      {
        public void run()
        {
          linkedText.setSelectionStart(startBefore);
          linkedText.setSelectionEnd(endBefore);
        }
      });
      

      这似乎是为了保护当前光标位置或选择。 (注意:这段代码必须已经在事件派发线程中运行了,但无论如何都需要invokeLater,否则它不起作用。)

      我有一个“is Mac”功能,所以我在测试中这样做了,但在所有平台上这样做可能不会造成任何伤害。

      【讨论】:

        【解决方案5】:

        我在查看 JavaDocs 时注意到 requestFocus()“不鼓励使用,因为它的行为取决于平台。”您应该改用requestFocusInWindow(),看看是否会出现同样的问题。

        requestFocusInWindow 是 Focus subsystem 的一部分,在 Java 1.4 中引入。

        附带说明,默认的 Apple 外观在 apple.laf 命名空间中至少有一个属性:apple.laf.useScreenMenuBar

        编辑:According to Sun,Macintosh 外观仅适用于 Mac。

        【讨论】:

        • 好的提示,我将尝试 requestFocusInWindow。另外,很遗憾我无法测试 Mac L&F,但至少知道这一点是件好事。
        • 不幸的是,requestFocusInWindow() 也有同样的问题。
        【解决方案6】:

        虽然确实鼓励使用 requestFocusInWindow() 而不是 requestFocus(),但它仍然会在 Mac 上产生相同的问题行为(例如,突出显示全文字段)。

        我开始工作的一个解决方法是在请求焦点后显式设置光标位置:

        JTextField.requestFocusInWindow();
        JTextField.setCaretPosition(JTextField.getDocument().getLength() - 1);
        

        注意“-1”是必须的,否则会继续高亮整个字段。

        我很想知道这个解决方案是否独立于平台。这是否会破坏所需的 Linux 或 Windows 行为?

        【讨论】:

        • 感谢您检查 requestFocusInWindow() 行为,因为我没有 Mac,所以我在这里瞎了眼。移动插入符号的位置并不理想,但也许可以将插入符号移动两次以使其回到应有的位置?
        【解决方案7】:

        Mac 将在字段获得焦点时选择文本字段的内容。如果您监听焦点更改事件,您可以恢复文本字段的状态。

        // JTextField linkedText
        // Cache the state of the JTextField prior to requesting focus
        final int
          startBefore = linkedText.getSelectionStart(),
          endBefore = linkedText.getSelectionEnd();
        linkedText.requestFocus(); // this was the original code line!
        
        // Use a focus listener to listen for the focus change and then
        // reset the selected text to protect the cursor position
        linkedText.addFocusListener ( new FocusListener()
        {
            public void focusGained( FocusEvent event ) {
                linkedText.setSelectionStart( startBefore );
                linkedText.setSelectionEnd( endBefore );
            }
        
            public void focusLost( FocusEvent event ) {
                // do nothing
            }
        } );
        

        【讨论】:

          【解决方案8】:

          感谢您分享您的想法。我在我的 java 应用程序上遇到了同样的问题,在我的 Windows 系统上没有问题,但在我的 Mac OS X Yosemite 上我无法更改输入。焦点不会停留在 JTextField 上。感谢这个帖子,我能够解决我的问题。

          如果您更改按钮和输入框的外观和感觉,您将保持焦点并可以再次输入。框架的重置保持标准 Mac OS 外观。

          这是我在 java main 方法中使用的代码。如果您想通过 main 方法中的 try-catch 代码解决问题。

          public class Venster extends JFrame {
          
              public static void main(String[] args) {
          
                  //Change L&F for mac
                  //Mac JTextField Bug Fix
                  try {
                      // Set cross-platform Java L&F (also called "Metal")
                      UIManager.setLookAndFeel(
                              UIManager.getCrossPlatformLookAndFeelClassName());
                  } catch (UnsupportedLookAndFeelException e) {
                      System.out.println("L&F not supported" + e.getMessage());
          
                  } catch (ClassNotFoundException e) {
                      System.out.println("Fout: " + e.getMessage());
                  } catch (InstantiationException e) {
                      System.out.println("Fout: " + e.getMessage());
                  } catch (IllegalAccessException e) {
                      System.out.println("Fout: " + e.getMessage());
                  }
          
                  //The app
                  JFrame frame = new JFrame();
                  frame.setSize(1000, 520);
                  frame.setResizable(false);
                  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  frame.setTitle("10 More Bullets by Frank Peters");
                  frame.setContentPane(new SpeelVeld());
                  frame.setVisible(true);
                  frame.setLocationRelativeTo(null);    //start app in center
              }
          }
          

          酸味: http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-04-29
            • 2012-03-10
            • 2015-12-21
            • 2012-05-28
            • 2011-05-11
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多