Java macl&;F问题:JTextField.requestFocus()的不同行为

Java macl&;F问题:JTextField.requestFocus()的不同行为,java,macos,look-and-feel,jtextfield,Java,Macos,Look And Feel,Jtextfield,我对JTextField.requestFocus()行为有一个问题,它在Mac OS X上似乎有所不同 以下是我的情况:我有一个与JList和JTextField的对话框。用户应该在文本字段中编写一个布尔表达式,该列表包含可能在表达式中输入的所有变量的名称。由于用户在单击列表中的变量后将继续输入表达式,因此程序将调用JTextField.requestFocus()。这样,您可以从列表中单击“pvalue”,然后键入“

我对JTextField.requestFocus()行为有一个问题,它在Mac OS X上似乎有所不同

以下是我的情况:我有一个与JList和JTextField的对话框。用户应该在文本字段中编写一个布尔表达式,该列表包含可能在表达式中输入的所有变量的名称。由于用户在单击列表中的变量后将继续输入表达式,因此程序将调用JTextField.requestFocus()。这样,您可以从列表中单击“pvalue”,然后键入“<0.05”,而无需单击中间的文本字段

这一切都可以在我的开发机器(Linux)上正常工作,但我从一个Mac用户那里得到一个错误报告,单击列表实际上会选择文本字段中的所有文本,这使得很容易意外地覆盖以前输入的内容

我怀疑这是Mac外观的一个问题,经过一些搜索后,似乎确实有一个“Quaqua.TextComponent.autoSelect”属性用于Mac外观,它似乎与此问题有关:

我的一般问题是:

  • 你能建议解决这个问题的方法吗
如果这个问题过于宽泛,那么对这些子问题的回答已经是一个很大的帮助:

  • 一个可能的解决方案是更改属性“Quaqua.TextComponent.autoSelect”。我该怎么做
  • 我甚至不知道什么是“夸夸”。它看起来像是一个定制的外观和感觉。Mac OS X的默认外观是什么?它是否具有类似于Quaqua.TextComponent.autoSelect的属性
  • 是否有可能仅为单个组件实例调整外观?如果是,怎么做
  • 有没有可能在我的Linux开发机器上设置Mac的外观,这样我就可以确认这个bug了(所有这些都是基于直觉和怀疑)?如果是,怎么做

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

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


我在查看JavaDocs时注意到,“由于其行为依赖于平台,因此不鼓励使用它。”您应该改用它,看看是否会出现同样的问题

requestFocusInWindow是Java 1.4中引入的

另一方面,默认的Apple外观在
Apple.laf
命名空间中至少有一个属性:
Apple.laf.useScreenMenuBar


编辑:,Macintosh外观仅在Macs上可用。

虽然使用
requestFocusInWindow()
确实比
requestFocus()
更受鼓励,但它仍然会在Macs上产生同样的问题行为(例如,突出显示全文字段)

我得到的一个解决方法是在请求焦点后显式设置光标位置:

JTextField.requestFocusInWindow();
JTextField.setCaretPosition(JTextField.getDocument().getLength() - 1);
注意“-1”是必需的,否则它将继续突出显示整个字段


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

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

很抱歉添加到一个旧问题,但我刚刚遇到这个问题,并使用了以下代码,这似乎比上一个示例更完整:

// 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”功能,所以我在一个测试中做了这个,但在所有平台上做它可能不会有任何伤害。

这似乎是Mac操作系统的一个缺陷。JTextFields在通过键盘选项卡循环获得焦点时选择其内容。如果插入点位于文本的中间,插入点将保留,整个文本将不被选择。

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

textfield.setCaret(新的DefaultCaret())。


您可以参考和查看更多详细信息。

当文本字段获得焦点时,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
    }
} );

谢谢你分享你的想法。我的java应用程序也有同样的问题,在我的windows系统上没有问题,但在我的Mac OS X Yosemite上,我无法更改输入。焦点不会停留在JTextField上。多亏了这个线程,我才能够解决我的问题

如果更改按钮和输入框的外观,则可以保持焦点,并可以再次键入。帧的重置保持标准Mac OS外观

这是我在java主方法中使用的代码。如果您想通过主方法中的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
    }
}
资源:

这很有帮助,但它看起来像是一种定制的外观和感觉,不一定是我的用户正在使用的。是的,它是默认MacOS L&F的扩展,不幸的是,它也改变了组件的行为(例如,在焦点上选择文本字段的内容)而且不仅修改了实际的L&F。我意识到在应用程序中很难处理所有这些问题,但您至少可以建议Quaqua的用户设置t