当JDialog中的JTextField可见时,将焦点放在该字段上



我有一个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也按预期工作。

然而,他的答案实际上并没有回答这个问题:那就是:发生了什么,为什么这次测试失败了?

最新更新