public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the dialog */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
MyDialog dialog = new MyDialog(new javax.swing.JFrame(), true);
dialog.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
}
});
}
The MyDialog class just has few combos and textfields and am populating combo with DB values. On selecting one combo value i fetch another value from DB to populate the next combo.
The above program runs the same way without using invokeLater threading. When does invokeLater becomes useful in Swing programming. I have read some about it, but all seems to be theoratical. What difference does the invokeLater makes to the application? Is it enough to use it just inside main method or it should also be used in action Listeners?
SwingUtilities.invokeLater and java.awt.EventQueue.invokeLater - are they same?
Nothing theoretical about it. It's very practical. The SwingUtilities.invokeLater()
method guarantees that the code within the Runnable
will run on the Event Dispatch Thread (EDT)
. This is important because Swing is not thread-safe, thus anything related to the GUI (Swing
, etc.) needs to run on the EDT
. The EDT
is a "it happens whenever it happens" thread that makes no guarantees about the order in which things are executed. If the GUI code is executed within a background thread (say, within a SwingWorker
instance), then it can throw errors. I learned this the hard way: in my learning years, executing GUI-changing code within a background thread caused random, inconsistent RuntimeException
s that I couldn't figure out. It was a good learning experience (SwingWorker
has a doInBackground()
method for background tasks and a done()
method for EDT
tasks).
In the same way you don't want to execute GUI code on a background thread, you also don't want to execute large operations (database queries, etc) on the EDT
. This is because the EDT
is dispatching all of the GUI events so everything on the EDT
should be very short and sweet. You can easily see this with a JProgressBar
set to indeterminate.
This SSCCE should illustrate it nicely. Notice the motion of the JProgressBar
as method()
is called, once on a background thread and once on a EDT
thread.
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
/**
*
* @author Ryan
*/
public class Test {
public static void main(String args[]) {
JFrame frame = new JFrame();
JProgressBar jpb = new JProgressBar();
jpb.setIndeterminate(true);
frame.add(jpb);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
new Task().execute();
}
public static void method() { // This is a method that does a time-consuming task.
for(int i = 1; i <= 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
}
static class Task extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() throws Exception {
/* Executing method on background thread.
* The loading bar should keep moving because, although method() is time consuming, we are on a background thread.
*/
method();
return null;
}
@Override
protected void done() {
/* Executing method on Event Dispatch Thread.
* The loading bar should stop because method() is time consuming and everything on the Event Dispatch Thread
* (like the motion of the progress bar) is waiting for it to finish.
*/
//
method();
}
}
}
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With