Swing: How do I run a job from AWT thread, but after a window was layed out?
- by java.is.for.desktop
My complete GUI runs inside the AWT thread, because I start the main window using SwingUtilities.invokeAndWait(...).
Now I have a JDialog which has just to display a JLabel, which indicates that a certain job is in progress, and close that dialog after the job was finished.
The problem is: the label is not displayed. That job seems to be started before JDialog was fully layed-out.
When I just let the dialog open without waiting for a job and closing, the label is displayed.
The last thing the dialog does in its ctor is setVisible(true).
Things such as revalidate(), repaint(), ... don't help either.
Even when I start a thread for the monitored job, and wait for it using someThread.join() it doesn't help, because the current thread (which is the AWT thread) is blocked by join, I guess.
Replacing JDialog with JFrame doesn't help either.
So, is the concept wrong in general? Or can I manage it to do certain job after it is ensured that a JDialog (or JFrame) is fully layed-out?
Simplified algorithm of what I'm trying to achieve:
Create a subclass of JDialog
Ensure that it and its contents are fully layed-out
Start a process and wait for it to finish (threaded or not, doesn't matter)
Close the dialog
I managed to write a reproducible test case:
EDIT Problem from an answer is now addressed:
This use case does display the label, but it fails to close
after the "simulated process", because of dialog's modality.
import java.awt.*;
import javax.swing.*;
public class _DialogTest2 {
public static void main(String[] args)
throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
final JLabel jLabel = new JLabel("Please wait...");
@Override
public void run() {
JFrame myFrame = new JFrame("Main frame");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setSize(750, 500);
myFrame.setLocationRelativeTo(null);
myFrame.setVisible(true);
JDialog d = new JDialog(myFrame, "I'm waiting");
d.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
d.add(jLabel);
d.setSize(300, 200);
d.setLocationRelativeTo(null);
d.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000); // simulate process
jLabel.setText("Done");
} catch (InterruptedException ex) {
}
}
});
d.setVisible(false);
d.dispose();
myFrame.setVisible(false);
myFrame.dispose();
}
});
}
}