SwingWorker, done() method not called
java, multithreading, swing, swingworker
Solution
All swing events are run inside the Event Dispatch Thread. So the `ChangeListener` that you have added to the `mainTabs` runs in the Event Dispatch Thread.
In the event listener you instantiate the `GuiWorker` and in that constructor you open the dialog by calling `dialog.setVisible(true);`.
Your JDialog instance is `modal` and calling `setVislbe(true)` on a modal dialog will block the calling thread, in your case the Event Dispatch Thread. So until the dialog is closed, the `gw.execute();` is not called. That is why your `done` method is not called until you close the dialog.
For your code to work, you can try not calling `setVisible(true)` in the constructor but provide a method from the `GuiWorker` to set the dialog's visibility. Then after calling `gw.execute();` call `gw.setVisible(true)`.
To clarify, try
class GuiWorker extends SwingWorker<Integer, Integer> {
private JFrame frame = new JFrame();
private JDialog dialog = new JDialog(frame, "Loadin data", true);
private JProgressBar progressBar = new JProgressBar();
private Statistics st = new Statistics();
public GuiWorker(GraphEditor editor, Statistics st) {
this.st = st;
Window mainWindow = SwingUtilities.windowForComponent(editor
.getGraphComponent().getParent());
dialog.setSize(400, 200);
int x = mainWindow.getX() + (mainWindow.getWidth() - dialog.getWidth())
/ 2;
int y = mainWindow.getY()
+ (mainWindow.getHeight() - dialog.getHeight()) / 2;
progressBar.setString("Have fun to wait some time...");
progressBar.setStringPainted(true);
progressBar.setIndeterminate(true);
dialog.add(progressBar);
dialog.setModal(true);
dialog.setLocation(x, y);
}
@Override
protected Integer doInBackground() throws Exception {
st.loadInitialData();
return 0;
}
@Override
protected void done() {
dialog.setVisible(false);
JLabel label = new JLabel("Task Complete");
dialog.getContentPane().remove(progressBar);
dialog.getContentPane().add(label);
dialog.getContentPane().validate();
dialog.setVisible(false);
}
public void setVisible(boolean visible) {
dialog.setVisible(visible);
}
}
and
mainTabs.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
switch (mainTabs.getSelectedIndex()) {
case 0:
case 1:
case 2: // stats tab
GuiWorker gw = new GuiWorker(editor,st);
gw.execute();
gw.setVisible(true);
break;
default:
break;
}
}
});
Problem
This is, simply an implementation of SwingWorker: ``` class GuiWorker extends SwingWorker<Integer, Integer> { private JFrame frame = new JFrame(); private JDialog dialog = new JDialog(frame, "Loadin data", true); private JProgressBar progressBar = new JProgressBar(); private Statistics st = new Statistics(); public GuiWorker(GraphEditor editor, Statistics st) { this.st = st; Window mainWindow = SwingUtilities.windowForComponent(editor .getGraphComponent().getParent()); dialog.setSize(400, 200); int x = mainWindow.getX() + (mainWindow.getWidth() - dialog.getWidth()) / 2; int y = mainWindow.getY() + (mainWindow.getHeight() - dialog.getHeight()) / 2; progressBar.setString("Have fun to wait some time..."); progressBar.setStringPainted(true); progressBar.setIndeterminate(true); dialog.add(progressBar); dialog.setModal(true); dialog.setLocation(x, y); dialog.setVisible(true); } @Override protected Integer doInBackground() throws Exception { st.loadInitialData(); return 0; } @Override protected void done() { dialog.setVisible(false); JLabel label = new JLabel("Task Complete"); dialog.getContentPane().remove(progressBar); dialog.getContentPane().add(label); dialog.getContentPane().validate(); dialog.setVisible(false); } } ``` The problem that `diaglog` never hides till I forcely close it (it must be hidden when task finished). I note that `loadInitialData()` method is a method of collecting some stats info from my `DB` that takes some few seconds. UPDATE: I am sure that `done()` method is called just when I close the `dialog`. UPDATE: Where I am using GuiWorker is here: ``` mainTabs.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { switch (mainTabs.getSelectedIndex()) { case 0: case 1: case 2: // stats tab GuiWorker gw = new GuiWorker(editor,st); gw.execute(); break; default: break; } } }); ```