Reputation: 3866
In my application, I would like to do something like
SwingWorker.done()
, execute the rest of my code)I started noticing problems: the code after my new WaitScreen().execute();
was being executed before it and I had to manually close the dialog to trigger the done()
.
To try to make sense of it, I took some simpler code, made it my own, and used it to emulate my problem. Here it is:
import java.awt.EventQueue; import java.awt.BorderLayout;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
public class SwingWorkerDialogTest
{
public static void main(String[] args)
{
new SwingWorkerDialogTest();
}
private JDialog dialog;
public SwingWorkerDialogTest()
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex)
{
}
catch (javax.swing.UnsupportedLookAndFeelException ex)
{
}
MyWorker worker = new MyWorker(true);
worker.execute();
new MyWorker(false).execute();
}
});
}
public class MyWorker extends SwingWorker<Object, Object>
{
private boolean runGUI;
public MyWorker(boolean b) { this.runGUI = b; }
@Override
protected Object doInBackground() throws Exception
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
if (runGUI)
{
getDialog().setVisible(true);
}
else
{
for (int j = 0; j < 30; j++)
{
System.out.println("j == " + j);
}
}
}
});
Thread.sleep(20000);
return null;
}
@Override
protected void done()
{
System.out.println("now in done...");
JDialog dialog = getDialog();
// Don't care, dismiss the dialog
//dialog.setVisible(false);
dialog.dispose();
}
}
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;
}
}
It was working fine when there was only worker
running. But, the instant I execute()
d another MyWorker
, my problem reoccurred. How do I remedy this?
Upvotes: 0
Views: 1105
Reputation: 347214
So, the point of a SwingWorker
is to allow you to execute long running/blocking tasks in a background thread, outside of the context of the Event Dispatching Thread, so you don't block the UI.
the code after my new WaitScreen().execute(); was being executed before it and I had to manually close the dialog to trigger the done()
Yes, that would to be expected, that's the whole point of a SwingWorker
. What's happening is, when you call execute a new Thread
is create and at some point the future, it will call (indirectly) your doInBackground
method, in the mean time, all the other threads (like the EDT) are allowed to carry on.
Using SwingUtilities.invokeLater
inside the SwingWorker
is also some what pointless, the worker is designed to provide functionality to make it easy to send updates back to the EDT.
Okay, in your case, a simple solution would be to call execute
first and then immediately display the dialog after in, thereby blocking the code execution at that point, for example...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
public class SwingWorkerDialogTest {
public static void main(String[] args) {
new SwingWorkerDialogTest();
}
private JDialog dialog;
public SwingWorkerDialogTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
}
MyWorker worker = new MyWorker(true);
worker.execute();
new MyWorker(false).makeItSo();
System.out.println("I'm free !");
}
});
}
public class MyWorker extends SwingWorker<Object, Object> {
private boolean runGUI;
public MyWorker(boolean b) {
this.runGUI = b;
}
public void makeItSo() {
execute();
getDialog().setVisible(true);
}
@Override
protected Object doInBackground() throws Exception {
for (int j = 0; j < 30; j++) {
System.out.println("j == " + j);
Thread.sleep(10);
}
Thread.sleep(20000);
return null;
}
@Override
protected void done() {
System.out.println("now in done...");
JDialog dialog = getDialog();
// Don't care, dismiss the dialog
//dialog.setVisible(false);
dialog.dispose();
}
}
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;
}
}
Upvotes: 1