Java LostFocus和InputVerifier,按相反的制表符顺序移动
我有一个GUI应用程序,它使用InputVerifier在产生焦点之前检查文本字段的内容。这一切都很正常。然而,昨天,我发现了一个问题——它似乎是一个bug,但我在任何地方都找不到任何关于它的提及。在我将此报告为bug之前,我想我会问:我是否遗漏了一些明显的东西 情况:Java LostFocus和InputVerifier,按相反的制表符顺序移动,java,swing,focus,Java,Swing,Focus,我有一个GUI应用程序,它使用InputVerifier在产生焦点之前检查文本字段的内容。这一切都很正常。然而,昨天,我发现了一个问题——它似乎是一个bug,但我在任何地方都找不到任何关于它的提及。在我将此报告为bug之前,我想我会问:我是否遗漏了一些明显的东西 情况: 带有输入验证程序的一组文本字段 所有控件上的FocusLost和FocusGain的侦听器,因此我可以看到发生了什么 一个单独的线程使用DefaultKeyboardFocusManager报告(每2秒)哪个控件具有焦点 我将
- 带有输入验证程序的一组文本字段
- 所有控件上的FocusLost和FocusGain的侦听器,因此我可以看到发生了什么
- 一个单独的线程使用DefaultKeyboardFocusManager报告(每2秒)哪个控件具有焦点
编辑:下面是一个显示问题的小示例程序。问题与额外的线程无关-线程只是为了使问题更加明显。如果有比赛条件,它是在摇摆的某处 要查看问题,请转到第二个文本框并将其清空。控件应保持焦点,除非按shift-tab键将其保留。与完整应用程序不同,错误似乎100%都发生在这里。在OpenJDK 6和Oracle Java 7下都是如此 这是一个非常明显的bug,而且它发生在多个Java环境中。因此,我怀疑我遗漏了一些明显的东西。有人吗
public class FocusBugDemo extends JFrame {
static JTextField txtOne = new JTextField("Ignore this control");
static JTextField txtTwo = new JTextField("Delete this text, then press shift-tab");
static JLabel lblFocus = new JLabel("");
static KeyboardFocusManager kfm = new DefaultKeyboardFocusManager();
public static void main(String[] args) {
new FocusBugDemo();
Thread t = new Thread() {
@Override
public void run() {
while(true) {
Component c = kfm.getFocusOwner();
String focusInfo = "elsewhere";
if (c == null) { focusInfo = "null";
} else if (c == txtOne) { focusInfo = "txtOne";
} else if (c == txtTwo) { focusInfo = "txtTwo";
}
lblFocus.setText(System.currentTimeMillis() + " - Focus owner " + focusInfo);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
};
t.start();
}
private FocusBugDemo() {
super("Focus bug demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setPreferredSize(new Dimension(300,100));
setLayout(new GridLayout(3,1));
NotEmpty validator = new NotEmpty();
txtOne.setInputVerifier(validator);
txtTwo.setInputVerifier(validator);
add(txtOne);
add(txtTwo);
add(lblFocus);
pack();
setVisible(true);
}
private class NotEmpty extends InputVerifier {
@Override
public boolean verify(JComponent input) {
JTextField txtField = (JTextField) input;
return (txtField.getText().length() > 0);
}
}
}
使用您的,我无法重现您在Mac OS X,Java 6上描述的效果,它支持@CatalinaIsland的观察。特别是,使用tab或shift-tab键,焦点永远不会留下空文本字段;只有在禁用帧时,焦点才会变为
null
我看到两个线程访问多个字段,根本没有同步。至少,您应该在t
中使用EventQueue.invokeLater()
来更新GUI,如下所述
更广泛的问题是:您试图使用t
解决什么焦点问题
import java.awt.Component;
import java.awt.DefaultKeyboardFocusManager;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import javax.swing.InputVerifier;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class FocusDemo {
private static final JTextField txtOne =
new JTextField("Ignore this control");
private static final JTextField txtTwo =
new JTextField("Delete this text, then press shift-tab");
private static final JLabel lblFocus = new JLabel("");
public static void main(String[] args) {
new FocusDemo();
Thread t = new Thread() {
@Override
public void run() {
while (true) {
EventQueue.invokeLater(new Runnable() {
KeyboardFocusManager kfm =
new DefaultKeyboardFocusManager();
@Override
public void run() {
Component c = kfm.getFocusOwner();
String focusInfo = "elsewhere";
if (c == null) {
focusInfo = "null";
} else if (c == txtOne) {
focusInfo = "txtOne";
} else if (c == txtTwo) {
focusInfo = "txtTwo";
}
lblFocus.setText(System.currentTimeMillis()
+ " - Focus owner " + focusInfo);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
}
};
t.start();
}
private FocusDemo() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame f = new JFrame("Focus bug demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setPreferredSize(new Dimension(300, 100));
f.setLayout(new GridLayout(3, 1));
NotEmpty validator = new NotEmpty();
txtOne.setInputVerifier(validator);
txtTwo.setInputVerifier(validator);
f.add(txtOne);
f.add(txtTwo);
f.add(lblFocus);
f.pack();
f.setVisible(true);
}
});
}
private class NotEmpty extends InputVerifier {
@Override
public boolean verify(JComponent input) {
JTextField txtField = (JTextField) input;
return (txtField.getText().length() > 0);
}
}
}
现在向Oracle报告为bug。要更快获得更好的帮助,请发布单独的线程?有时?听起来像是一场数据竞赛。如何同步对数据共享数据的访问?是否应该在?+1上为创建GUI。如上所述,线程“t”与问题完全无关-问题仍然存在。线程“t”的出现只是为了通过不断显示哪个控件具有焦点来使问题更加明显。在Linux下运行时,文本字段在最新版本的OracleJava7和OpenJDK6下失去了shift选项卡的焦点。我没有在Windows或MacOS下进行测试。我无法在Ubuntu 10、OpenJDK 6上复制您或我的示例所描述的效果。感谢您提供的信息-这真的很奇怪,因为我在两个不同的系统上复制了效果。让我们看看甲骨文的人都说了些什么-我会根据需要在错误报告下面提供更多的信息…链接在那里(点击错误编号)-很明显,链接在甲骨文实际工作之前只需要几天时间。。。