// 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");
}});
}
}
}
答案 0 :(得分:4)
显然是某种竞争条件。我认为它不像Erick Robertson那样简单。 Dialog的show()
代码非常复杂,它包含一些从事件调度线程调用的特殊逻辑,它还将事件发布到事件队列。也许发布事件的顺序会受到线程延迟的影响。
也许你所需要的是正如Skip Head指出的那样,invokeAndWait将阻止,直到对话框关闭。SwingUtilities.invokeAndWait()
,这样你就可以保证setVisible(true)
在你调用setVisible(false)
之前已经完成了执行。
你为什么还需要呢?
编辑:这是我发生的事情的情景:
setVisible(true)
事件EDIT2:看起来ProgressMonitor具有您尝试实施的功能。
答案 1 :(得分:2)
事实证明,当你显示()/ setVisible(true)一个模态对话框时会发生的事情是在show / setVisible调用中运行第二个事件调度循环。一旦你了解它,这就很有意义。考虑到这一点,我最终得到了这段代码:
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);
}
答案 2 :(得分:1)
您可以尝试dispose()
对话框而不是隐藏它,但如果您想再次显示它,则需要重建它。
答案 3 :(得分:0)
setVisible(true)和setVisible(false)之间的一点睡眠时间(100ms)在某些情况下解决了这个问题。另见https://bugs.openjdk.java.net/browse/JDK-5109571 当尝试使用dispose而不是setVisible(false)时,似乎没有出现竞争条件