【问题标题】:Put focus on a JTextField in JDialog when latter made visible当后者可见时,将焦点放在 JDialog 中的 JTextField
【发布时间】:2016-05-05 17:43:55
【问题描述】:

我有一个 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 没有焦点。谁能解释一下是怎么回事?

【问题讨论】:

    标签: java swing focus jdialog


    【解决方案1】:

    大多数对话框都是模态的,这意味着 setVisible(true) 语句之后的语句在对话框关闭之前不会执行。

    默认情况下,焦点将转到对话框上的第一个组件。

    如果由于某种原因您需要关注不同的组件,请查看Dialog Focus 以获得允许您控制哪个组件获得焦点的解决方案。

    此解决方案使用AncestorListener 在组件显示在可见对话框/框架上后将焦点置于组件上。

    【讨论】:

    • "setVisible(true) 语句之后的语句直到对话框关闭才执行" ...好的...解释了很多,谢谢。你有没有想过为什么getFocusOwner()会返回null?现在检查您的对话焦点...
    • 另外,如果可以的话...我熟悉 setVisible(true) 阻塞线程(甚至是 EDT)...并且花了很多时间摸不着头脑(新的“事件调度泵”等)。但是为什么,在我的第二个代码 sn-p 中,它没有阻塞那个 EDT 线程?
    • But why, in my second code snippet, - 您要解决的具体问题是什么?为什么你甚至关心什么有焦点?仅供参考,您不能总是假设所有代码都是按顺序执行的。与使用invokeAndWait(...) 的方式相同,其他代码可以使用invokeLater(),这意味着在执行断言语句时可能无法确定焦点。发布一个正确的SSCCE 来证明问题。代码 sn-ps 无济于事,因为我们不了解如何使用代码的上下文。
    • @mikerodent,不要忘记点击复选标记“接受”答案,这样人们就知道问题已经解决了。
    • 我必须先做一些实验,看看它是否真的解决了......我也在考虑组建一个SSCCE。但我会在适当的时候将其标记为已解决......
    【解决方案2】:

    啊哈...事实证明这是 JUnit 和 Java GUI 的“陷阱”之一。

    我的代码中的测试失败了……但下面的代码没有:

        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 按预期工作。

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

    【讨论】:

      猜你喜欢
      • 2017-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-30
      • 2013-12-26
      • 2011-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多