问题
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;
}
}
来源:https://stackoverflow.com/questions/13131061/safely-open-and-close-modal-jdialog-using-swingworker