Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Swing模态对话框拒绝关闭-有时!_Java_Multithreading_Swing_Modal Dialog_Jdialog - Fatal编程技术网

Java Swing模态对话框拒绝关闭-有时!

Java Swing模态对话框拒绝关闭-有时!,java,multithreading,swing,modal-dialog,jdialog,Java,Multithreading,Swing,Modal Dialog,Jdialog,这显然是某种种族状况。我认为这并不像埃里克·罗伯逊的回答那么简单。Dialog的show()代码相当复杂,它包含一些从事件分派线程调用的特殊逻辑,并且还将事件发布到事件队列。可能事件的发布顺序受到线程延迟的影响 也许您需要的是SwingUtilities.invokeAndWait(),这样您可以保证setVisible(true)在调用setVisible(false)之前已经完成执行。正如Skip Head指出的,invokeAndWait将一直阻塞,直到对话框关闭 你为什么需要它呢 编辑:

这显然是某种种族状况。我认为这并不像埃里克·罗伯逊的回答那么简单。Dialog的
show()
代码相当复杂,它包含一些从事件分派线程调用的特殊逻辑,并且还将事件发布到事件队列。可能事件的发布顺序受到线程延迟的影响

也许您需要的是
SwingUtilities.invokeAndWait()
,这样您可以保证
setVisible(true)
在调用
setVisible(false)
之前已经完成执行。正如Skip Head指出的,invokeAndWait将一直阻塞,直到对话框关闭

你为什么需要它呢

编辑:这是我对正在发生的事情的设想:

  • 调用d.show()来发布
    setVisible(true)
    事件
  • 调度程序将线程置于睡眠状态,EDT启动并开始执行第一个事件
  • EDT在第一个任务完成并发布显示对话框的实际事件之前被踢出
  • 线程执行d.hide()以发布setVisible(false)事件。线程已完成,EDT开始工作
  • EDT完成了第一个任务,将其显示事件放入事件队列
  • 它转到下一个事件,瞧,这是setVisible(false)事件
  • 它扰乱了对话框的整个状态,并保持可见和无响应

  • EDIT2:看起来具有您试图实现的功能。

    您可以尝试
    dispose()
    该对话框,而不是隐藏它,但如果您想再次显示它,则需要重新生成它。

    因此,当您显示()/setVisible(true)时会发生什么情况模式对话框是在调用show/setVisible中运行第二个事件分派循环。一旦你知道了,这就很有道理了。考虑到这一点,我最终得到了以下代码:

    // This is supposed to show a modal dialog and then hide it again. In practice,
    // this works about 75% of the time, and the other 25% of the time, the dialog
    // stays visible.
    // This is on Ubuntu 10.10, running:
    // OpenJDK Runtime Environment (IcedTea6 1.9) (6b20-1.9-0ubuntu1)
    
    // This always prints
    // setVisible(true) about to happen
    // setVisible(false) about to happen
    // setVisible(false) has just happened
    // even when the dialog stays visible.
    
    package modalproblemdemo;
    
    import java.awt.Frame;
    import javax.swing.JDialog;
    import javax.swing.SwingUtilities;
    
    public class Main {
        public static void main(String[] args) {
            final Dialogs d = new Dialogs();
            new Thread() {
                @Override
                public void run() {
                    d.show();
                    d.hide();
                }
            }.start();
        }
    
        static class Dialogs {
            final JDialog dialog;
    
            public Dialogs() {
                dialog = new JDialog((Frame) null, "Hello World", /*modal*/ true);
                dialog.setSize(400, 200);
            }
    
            public void show() {
                SwingUtilities.invokeLater(new Runnable() { public void run() {
                    dialog.setLocationRelativeTo(null);
                    System.out.println("setVisible(true) about to happen");
                    dialog.setVisible(true);
                }});
            }
    
            public void hide() {
                SwingUtilities.invokeLater(new Runnable() { public void run() {
                    System.out.println("setVisible(false) about to happen");
                    dialog.setVisible(false);
                    System.out.println("setVisible(false) has just happened");
                }});
            }
        }
    }
    
    在某些情况下,setVisible(true)和setVisible(false)之间有一点睡眠时间(100ms)可以解决问题。另见
    当尝试使用dispose而不是setVisible(false)时,似乎不会出现竞争条件

    InvokeAndWait in show()导致模式对话框阻塞等待关闭。我想这就是Zarkonnen在所有额外线程中试图避免的。我需要它作为一个“请等待,处理”模式对话框,告诉用户程序正在工作。它需要是模态的,以阻止用户在程序繁忙时单击按钮('因为这样EDT和工作线程都将处于操作状态)。@Zarkonnen:而且事件有时非常短,并导致竞争条件?试着把这两种方法放在一个
    同步的
    块中,也许它会起作用。@tulskiy ProgressMonitor的窗口实际上不是模态的!你能使对话框不具有模态吗?然后你就可以关闭它,而不必乱搞线程。两年后回答你自己的问题,请参见:+1。有奉献的徽章吗?
    
    public void runBlockingTask(final String taskName, final BlockingTask bt) {
        SwingUtilities.invokeLater(new Runnable() { public void run() {
            new Thread("Worker Thread: " + taskName) {
                @Override
                public void run() {
                    bt.run();
                    progressDialog.setVisible(false);
                }
            }.start();
        }});
        // NB This causes the event dispatch loop to be run inside this call,
        // which is why we need  to put everything after setVisible into an
        // invokeLater.
        progressDialog.setVisible(true);
    }