我有一个JDialog的子类。。。被覆盖的setVisible方法如下所示:
public void setVisible( boolean visible ){
super.setVisible( visible );
if( visible ){
inputJTF.requestFocus();
}
}
事实上,当我显示JDialog时,焦点是联合特遣部队。。。但后者恰好也是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 );
}
});
所以事实上我被告知"焦点所有者"是空的。。。联合特遣部队没有重点。有人能解释一下发生了什么吗?
大多数对话框都是模态的,这意味着在关闭对话框之前,setVisible(true)语句之后的语句不会执行。
默认情况下,焦点将转到对话框上的第一个组件。
如果出于某种原因,您需要关注不同的组件,请查看Dialog focus,以获得一个允许您控制哪个组件获得焦点的解决方案。
此解决方案使用AncestorListener
在组件显示在可见对话框/框架上后将焦点放在该组件上。
啊哈。。。事实证明,这是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
所需的有限时间有关。
Rob Camick的回答很有趣,RequestFocusListener
也按预期工作。
然而,他的答案实际上并没有回答这个问题:那就是:发生了什么,为什么这次测试失败了?