Mac L& F问题:JTextField.requestFocus()的不同行为

时间:2009-10-09 12:27:53

标签: java macos look-and-feel jtextfield

我遇到了Mac OS X上看似不同的JTextField.requestFocus()行为问题。

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

这一切在我的开发机器(Linux)上运行正常,但是我从Mac用户那里得到了一个错误报告,点击列表实际上选择了文本字段中的所有文本,这样就很容易意外地覆盖之前输入的内容。

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

我的一般问题是:

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

如果过于宽泛,对这些子问题的回答已经是一个很大的帮助:

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

8 个答案:

答案 0 :(得分:4)

似乎这是Mac OS的一个错误。 JTextFields通过键盘选项卡循环获得焦点时选择其内容。如果插入点位于文本的中间,则插入点将保留,并且不会选择整个文本。

作为一种解决方法,您可以使用以下内容覆盖此行为,它适用于我:

textfield.setCaret(new DefaultCaret()).

有关详细信息,请参阅thisthis

答案 1 :(得分:2)

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

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

Quaqua Look & Feel - User Guide

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

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

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

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

答案 4 :(得分:1)

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

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

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

注意“-1”是必要的,否则它将继续突出显示整个字段。

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

答案 5 :(得分:1)

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

// 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,否则它不起作用。)

我有一个'是Mac'功能,所以我在测试中做了这个,但是在所有平台上做这件事可能没什么坏处。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

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

这是我在java 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
    }
}

SOURE: 的 http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html