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