【问题标题】:How can modal dialog wait, if event dispatching thread is not paused?如果事件调度线程没有暂停,模式对话框如何等待?
【发布时间】:2014-04-13 19:15:55
【问题描述】:

在下面的示例中,模式对话框在事件调度线程内打开。由于对话框是模态的,方法setVisible()在关闭之前不会返回。

有人可能会怀疑这是导致事件调度线程暂停,但这是错误的,因为按钮正在运行。

因此,setVisible() 方法没有阻塞线程。

问题是:是否可以在不阻塞过程的情况下显示模态对话框?

package tests.javax.swing;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Try_JDialog_Modality2 {

    private static final Logger log = LoggerFactory.getLogger(Try_JDialog_Modality2.class);

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                AbstractAction popupAction = new AbstractAction("popup") {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JOptionPane.showMessageDialog(null, "popup");
                    }

                };

                JDialog dialog = new JDialog((JFrame)null, true);
                dialog.setLayout(new FlowLayout());
                dialog.add(new JButton(popupAction));

                dialog.pack();
                dialog.setLocationRelativeTo(null);

                dialog.setVisible(true);

                log.debug("After set visible");



            }
        });


    }

}

更新

我可以用下面的 sn-p 做同样的事情:

//dialog.setVisible(true);
            new Thread(new Runnable() {

                @Override
                public void run() {
                    dialog.setVisible(true);
                }
            }).start();

            log.debug("After set visible");

有没有更短的方法?

【问题讨论】:

    标签: java multithreading swing modal-dialog


    【解决方案1】:

    你的问题:

    问题是:是否可以在不阻塞过程的情况下显示模态对话框?

    是的,在显示模式对话框之前调用方法。对于某些事情,这可能最好使用回调类型的设置来完成,例如使用 PropertyChangeListener 或其他类型的侦听器。如果在可视化模态对话框之前设置并调用它,它应该可以工作。

    至于您问题的 how 部分,我相信它会阻止对其他窗口的输入,但不会停止 Swing 事件线程。不过,它确实会停止调用代码的程序流,可能是通过调用SwingUtilities.invokeAndWait(...)。最适合您查看 Swing 源代码了解详细信息。


    编辑 关于您的更新,切勿这样做:

    new Thread(new Runnable() {
    
        @Override
        public void run() {
            dialog.setVisible(true);
        }
    }).start();
    

    因为您现在保证启动 Swing 事件线程的对话框关闭

    【讨论】:

    • 如果它不停止事件线程,那么为什么必须用setVisible()停止程序?可以从单独的线程运行setVisible(),但是还有其他方法吗?
    【解决方案2】:

    dialog.setVisible(true); 应在 AWT Dispatcher 线程上运行。所以你应该反过来做。

    public buttonPressed_OpenDialog_and_doTask(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                /* my worker background task */
                dialog.dispose(); // at the end of task call this
            }
            }).start();
        dialog.setVisible(true);
        // we will continue when worker thread finishes
    }
    

    请注意,即使您阻塞了 AWT 事件调度程序线程(通过方法 setVisible())。 AWT 事件调度程序线程仍在以某种方式运行 - 所以所有 AWT 通知都像往常一样工作。见doc dialog.setVisible()

    请注意,即使后台任务太快并且在前一个线程中调用dialog.setVisible(true) 之前调用dialog.dispose(),一切正常。幸运的是 dialog.dispose() 礼貌地等到对话框出现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-16
      • 1970-01-01
      • 1970-01-01
      • 2016-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多