Roy Tang

Programmer, engineer, scientist, critic, gamer, dreamer, and kid-at-heart.

Blog Notes Photos Links Archives About

I have an applet that calls a JDialog that contains a JProgressBar component. I subclass the JDialog to expose a method to update the JProgressBar, something like:

public class ProgressDialog extends javax.swing.JDialog {
    public void setProgress(double progress) {
        jProgressBar1.setValue(jProgressBar1.getMinimum() + (int) (progress * jProgressBar1.getMaximum()));
    }
    ...
}

I use this dialog in the following manner:

public void test() throws Exception {
    progressDialog = new ProgressDialog(null, true);

    try {
        progressDialog.setLocationRelativeTo(null);

        // show the dialog
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                progressDialog.setVisible(true);
            }
        });

        // business logic code that calls progressDialog.setProgress along the way
        doStuff();
        
    } finally {
        progressDialog.setVisible(false);
        progressDialog.dispose();
    }
}

It works fine on Windows/any browser. However, when invoking the above function on Firefox 2/3/3.5 on a Mac, the progressDialog is displayed indefinitely, i.e. it doesn’t close.

I suspected that calling setVisible(true) inside the EventQueue was causing the problem, since it’s a blocking call and might block the queue completely, so I tried changing it to:

        // show the dialog
        new Thread() {
            public void run() {
                progressDialog.setVisible(true);
            }
        }.start();

With this change, the progressDialog now closes correctly, but a new problem emerged - the contents of the dialog (which included the progressbar, an icon and a JLabel used to show a message string) were no longer shown inside the dialog. It was still a problem only on Mac Firefox.

Any ideas? I realize it’s probably some AWT threading issue, but I’ve been at this for a couple of days and can’t find a good solution. Wrapping the doStuff() business logic in a separate new Thread seems to work, but it’s not easy to refactor the actual business logic code into a separate thread, so I’m hoping there’s a simpler solution.

The envt is: Mac OSX 10.5 Java 1.5 Firefox 2/3/3.5

Comments

Found out that the problem was that the applet function was executing inside the AWT dispatcher thread, therefore the thread blocks and no events are processed until the applet function finishes execution.

Solution was to move the processing logic into a separate thread spawned by the ProgressDialog object before calling setVisible(true). setVisible(true) would block the main thread but still allow the event dispatcher to continue processing, hence rendering the contents of the dialog until the spawned thread calls setVisible(false) to hide the dialog.