我有一个JDialog的子类...重写的setVisible方法如下所示:
public void setVisible( boolean visible ){
super.setVisible( visible );
if( visible ){
inputJTF.requestFocus();
}
}
事实上,当我显示JDialog时,焦点是在JTF上...但后者恰好也是JDialog中的“第一个”组件(NORTH面板),所以这并不奇怪
但我的测试代码告诉我其他事情:
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
app.mainFrame.searchDlg.setVisible( true );
// all 3 of these asserts fail...
assertTrue( app.mainFrame.searchDlg.inputJTF.hasFocus() );
Component focusOwner = app.mainFrame.searchDlg.getFocusOwner();
assertFalse( focusOwner == null );
assertTrue( String.format( "# focus owner %s", focusOwner.getClass()), focusOwner == app.mainFrame.searchDlg.inputJTF );
}
});
...所以实际上我被告知“焦点所有者”为空......而且JTF没有焦点。谁能解释一下发生了什么?
答案 0 :(得分:3)
大多数对话框都是模态的,这意味着在关闭对话框之前,不会执行setVisible(true)语句之后的语句。
默认情况下,焦点将转到对话框的第一个组件。
如果由于某种原因您需要专注于不同的组件,请查看Dialog Focus以获得一个解决方案,以便您控制哪个组件得到关注。
一旦组件显示在可见的对话框/框架上,此解决方案使用AncestorListener
将焦点放在组件上。
答案 1 :(得分:0)
Aha ...这是JUnit和Java GUI的“Gotcha”之一。
我的代码中的测试失败了...但是以下代码没有:
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
searchDlg.setVisible( true );
assertTrue( searchDlg.queryString == null );
}
});
Robot robot = new Robot();
robot.delay( 10 );
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
// now passes
assertTrue( app.mainFrame.searchDlg.inputJTF.hasFocus() );
}
});
...如果robot.delay()
减少到1或不存在,则失败发生。
显然,这与实现JDialog
所需的有限时间有关。
罗布·卡米克的回答很有趣,RequestFocusListener
按预期工作。
然而,他的答案实际上并没有回答这个问题:这是怎么回事?为什么这个测试会失败?