Zarkonnen Zarkonnen - 6 months ago 17
Java Question

Swing modal dialog refuses to close - sometimes!

// 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() {
public void run() {;

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() {
System.out.println("setVisible(true) about to happen");

public void hide() {
SwingUtilities.invokeLater(new Runnable() { public void run() {
System.out.println("setVisible(false) about to happen");
System.out.println("setVisible(false) has just happened");


So it turns out that what happens when you show()/setVisible(true) a modal dialog is that a second event dispatch loop is run within the call to show/setVisible. Which makes perfect sense once you know about it. With that in mind, I ended up with this code:

public void runBlockingTask(final String taskName, final BlockingTask bt) {
    SwingUtilities.invokeLater(new Runnable() { public void run() {
        new Thread("Worker Thread: " + taskName) {
            public void run() {
    // 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.