为什么这个 MyJDialogTest 对话框会在延时 3 秒后才显示?

2018-06-23 11:26:48 +08:00
 codechaser
package Chapter10;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;

public class DialogTest extends JFrame {

    public DialogTest(){
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(400,300);

        JPanel panel = new JPanel();

        JButton button = new JButton("MyJDialog");
        button.addActionListener(e -> {
            new MyJDialog(DialogTest.this, "Test", false).setVisible(true);

            try{
                Thread.sleep(3000);
            }catch (InterruptedException ex){

            }

            System.out.println("button's actionListener runs in thread: "+Thread.currentThread());
        });
        panel.add(button);

        add(panel);

        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(DialogTest::new);
    }
}

class MyJDialog extends JDialog{
    public MyJDialog(JFrame parent, String title, boolean modality){
        super(parent,title,modality);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        add(new JLabel("<html><h1><i>Bob</i></h1><hr>By Liao Maosheng</html>"),BorderLayout.CENTER);

        System.out.println("JDialog runs in thread: "+Thread.currentThread());
        JButton ok = new JButton();
        ok.setText("OK");
        ok.addActionListener(e -> {
//            setVisible(false);
            dispose();
        });

        add(ok,BorderLayout.SOUTH);

        setSize(200,200);
    }
}

这里我发现 MyJDialogTest 也是运行在事件派遣线程里,设置了 modality 为 false,那么这里 MyDialogTest.setVisible()好像是立马返回了的,然后立刻开始延时,导致事件派遣队列不能更新 MyJDialogTest,所以这里的 setVisible 应该是异步调用吧?同一个线程里也能异步调用吗?

1562 次点击
所在节点    Java
4 条回复
kaneg
2018-06-23 11:46:39 +08:00
Java 的 UI 是在 EDT 单线程里运行的,sleep 把 EDT 给阻塞了 3 秒,自然后续的 UI 改动就是在 3 秒以后了
verrickt
2018-06-23 12:06:52 +08:00
做 WPF 的无条件猜测下,DialogTest 的 ctor 在 UI 线程上跑,sleep 阻塞了 ui 线程,所以 delay3 秒。
codechaser
2018-06-23 13:52:42 +08:00
@kaneg 你好!这个 setVisible 算不算异步呢?我看到 doc 里面有这一段话:
```
public void setVisible(boolean b)
Shows or hides this Dialog depending on the value of parameter b.
Overrides:
setVisible in class Window
Parameters:
b - if true, makes the Dialog visible, otherwise hides the Dialog. If the dialog and/or its owner are not yet displayable, both are made displayable. The dialog will be validated prior to being made visible. If false, hides the Dialog and then causes setVisible(true) to return if it is currently blocked.
Notes for modal dialogs.

setVisible(true): If the dialog is not already visible, this call will not return until the dialog is hidden by calling setVisible(false) or dispose.
setVisible(false): Hides the dialog and then returns on setVisible(true) if it is currently blocked.
It is OK to call this method from the event dispatching thread because the toolkit ensures that other events are not blocked while this method is blocked.
See Also:
Window.setVisible(boolean), Window.dispose(), Component.isDisplayable(), Component.validate(), isModal()
```
codechaser
2018-06-23 13:53:43 +08:00
@verrickt 谢谢你!能抽空看一下我回复楼上的吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/465223

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX