Safely open and close modal JDialog (using SwingWo

2019-01-28 02:25发布

问题:

I needed a way to get some data from a database and prevent the user from modifying existing data for that moment.

I created a SwingWorker to make the db update and a modal JDialog to show user what is going on (with a JProgressBar). The modal dialog has defaultCloseOperation set to DO_NOTHING, so it can only be closed with a proper call - I use setVisible(false).

MySwingWorkerTask myTask = new MySwingWorkerTask();
myTask.execute();
myModalDialog.setVisible(true);

The SwingWorker does some stuff within doInBackground() and lastly it calls:

myModalDialog.setVisible(false);

My only concern and my question: Is is possible that the SwingWorker executes the setVisible(false) before it is setVisible(true) in the line after worker spawn?

If so the setVisible(true) could block forever (the user can't close the modal window).

Do I have to implement something as:

while (!myModalDialog.isVisible()) {
    Thread.sleep(150);
}
myModalDialog.setVisible(false);

to make sure it will actually get closed?

回答1:

Generally, yes.

What I would do is in your doInBackground method is use SwingUtilities.invokeLater to show the dialog and in your done method hide the dialog.

This should mean that even if the dialog doesn't make it to the screen you gain a little more control over the flow...

The minor issue is you're now going to have to pass the dialog to the worker so it can gain control over it...

public class TestSwingWorkerDialog {

    public static void main(String[] args) {
        new TestSwingWorkerDialog();
    }
    private JDialog dialog;

    public TestSwingWorkerDialog() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                MyWorker worker = new MyWorker();
                worker.execute();

            }
        });
    }

    public class MyWorker extends SwingWorker<Object, Object> {

        @Override
        protected Object doInBackground() throws Exception {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    getDialog().setVisible(true);
                }
            });
            Thread.sleep(2000);

            return null;
        }

        @Override
        protected void done() {
            System.out.println("now in done...");
            JDialog dialog = getDialog();
            // Don't care, dismiss the dialog
            dialog.setVisible(false);
        }

    }

    protected JDialog getDialog() {
        if (dialog == null) {

            dialog = new JDialog();
            dialog.setModal(true);
            dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
            dialog.setLayout(new BorderLayout());
            dialog.add(new JLabel("Please wait..."));
            dialog.setSize(200, 200);
            dialog.setLocationRelativeTo(null);

        }

        return dialog;
    }

}