我遇到了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
我的一般问题是:
如果过于宽泛,对这些子问题的回答已经是一个很大的帮助:
答案 0 :(得分:4)
似乎这是Mac OS的一个错误。 JTextFields通过键盘选项卡循环获得焦点时选择其内容。如果插入点位于文本的中间,则插入点将保留,并且不会选择整个文本。
作为一种解决方法,您可以使用以下内容覆盖此行为,它适用于我:
textfield.setCaret(new DefaultCaret()).
答案 1 :(得分:2)
要修改默认行为,可以在初始化UI组件之前将系统属性设置为false:System.setProperty("Quaqua.TextComponent.autoSelect", "false");
要修改单个组件,可以使用JTextField#putClientProperty("Quaqua.TextComponent.autoSelect", Boolean.FALSE);
。
您可以在此处找到其他MacOS L& F特定属性:
答案 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 强>