Question

I am developing an Java application on the NetBeans Framework (the RCP). When the application runs and is Visible I want to show a "Please Wait" Dialog box that will disable the user to use the GUI until the threads that are running are complete. Please take a look at my code below. The way it works right now, it displays the "Please Wait" Dialog box before the application is Visible. Once again, I want to show the "Please Wait" Dialog when the application is Visible, not before. How do I do this?

public final class MyTopComponent extends TopComponent {

    public CoreTopComponent() {
        initComponents();
    }

    @Override
    public void componentOpened() {

            //Show a Dialog ontop of the application with a Please Wait message so that the user cannot use the application until the following threads
            //are complete. The Dialog is supposed to automatically close once the threads are complete.

            JOptionPane.showOptionDialog(this, "Please Wait...",
            "Please Wait...", JOptionPane.PLAIN_MESSAGE,
            JOptionPane.PLAIN_MESSAGE, null, new Object[] {},
            null);


            //There are 10 threads like the following 2 that perform something and in the end update the GUI

            final Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    //Step 1 - Create class that initializes configuration

                    //Step 2 - Create class that performs something using configuration

                    //Step 3 - Update GUI on the EDT using SwingUtilities.invokeLater
                }
            });
            t1.start();

            final Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    //Step 1 - Create class that initializes configuration

                    //Step 2 - Create class that performs something using configuration

                    //Step 3 - Update GUI on the EDT using SwingUtilities.invokeLater
                }
            });
            t2.start(); 
    }


    @Override
    public void componentClosed() {

    }

    void writeProperties(java.util.Properties p) {
        // better to version settings since initial version as advocated at
        // http://wiki.apidesign.org/wiki/PropertyFiles
        p.setProperty("version", "1.0");
        // TODO store your settings
    }

    void readProperties(java.util.Properties p) {
        String version = p.getProperty("version");
        // TODO read your settings according to their version
    }
}

I tried to use the following, but still the same happens:

@Override
public void componentShowing() {
    JOptionPane.showOptionDialog(this, "Please Wait...",
            "Please Wait...", JOptionPane.PLAIN_MESSAGE,
            JOptionPane.PLAIN_MESSAGE, null, new Object[]{},
            null);
}
Was it helpful?

Solution

You can use the ProgressUtils.showProgressDialogAndRun() family of methods to show a progress bar in the center of the UI which blocks the UI until your task is done.

Implementing the ProgressRunnable interface will give your tasks access to the ProgressHandle. Then, using the showProgressDialogAndRun(ProgressRunnable<T> operation, String displayName, boolean includeDetailLabel) method you can set the detail label for each sub-task that you need to run.

Here's a snippet showing the different ways that you could do this. The main task in this scenario is the "Running Startup" task. It drives all of the sub-tasks, passing in the ProgressHandle to each so that each sub-task can set the detail label:

    ...
    final List<ProgressRunnable> tasks = new ArrayList<ProgressRunnable>();
    tasks.add(new ProgressRunnable<Object>() {
        @Override
        public Object run(ProgressHandle ph) {
            ph.progress("Work unit 1", 1);
            return null;
        }
    });
    tasks.add(new CancellableTask());
    ProgressUtils.showProgressDialogAndRun(new ProgressRunnable<Void>() {
        @Override
        public Void run(ProgressHandle ph) {
            // run all tasks passing in the ProgressHandle to each
            for (ProgressRunnable task : tasks) {
                task.run(ph);
            }
            return null;
        }
    }, "Running Startup", true);
    ...
    // will show a Cancel button on the progress UI
    private class CancellableTask implements ProgressRunnable<Object>, Cancellable {

    @Override
    public Object run(ProgressHandle ph) {
        ph.progress("Cancellable work unit", 2);
        return null;
    }

    @Override
    public boolean cancel() {
        // clean up 
        return true;
    }
}

OTHER TIPS

JOptionPane creates modal JDialogs. In order to avoid this, you can make it non modal by creating a thread:

    Thread waitThread = new Thread(new Runnable(){
        public void run(){
            JOptionPane.showOptionDialog(rootPane, "Please Wait...",
                "Please Wait...", JOptionPane.PLAIN_MESSAGE,
                JOptionPane.PLAIN_MESSAGE, null, new Object[] {},
                null);
    }

Call it by:

waitThread.start();

Notice that I change the parent component to rootPane instead of null, but you can do this based on the needs of your application. This will solve your problem and allow the rest of the code to run for while the dialog is up.

Make sure you are calling it before your other threads, so that they can run while this dialog is up.

Here is a similar question:

Showing "JOptionPane.showMessageDialog" without stopping flow of execution

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top