4

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

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

这一切在我的开发机器(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 的外观和感觉,以便我可以真正确认这个错误(以上所有内容都是基于预感和怀疑)?如果是这样,怎么做?
4

8 回答 8

5

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

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

textfield.setCaret(new DefaultCaret()).

更多细节可以参考thisthis

于 2013-06-14T08:02:08.513 回答
2

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

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

Quaqua 外观和感觉 - 用户指南

于 2009-10-09T13:05:05.820 回答
2

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

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

于 2011-01-07T17:25:15.887 回答
2

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

于 2010-01-18T05:22:28.263 回答
1

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

requestFocusInWindow 是Java 1.4 中引入的Focus 子系统的一部分。

附带说明一下,默认的 Apple Look and Feel 在命名空间中至少有一个属性apple.lafapple.laf.useScreenMenuBar

编辑:根据 Sun的说法,Macintosh 的外观和感觉仅适用于 Mac。

于 2009-10-09T15:22:36.853 回答
1

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

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

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

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

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

于 2009-10-10T23:31:34.863 回答
0

感谢您分享您的想法。我在我的 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

于 2014-12-23T10:14:10.790 回答
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
    }
} );
于 2013-10-08T16:05:13.570 回答