I have a JAVA6 GUI handling data import to our database. I have implemented a working JProgressBar. I understand that changes made to the GUI must be done via the event dispatch thread--which I do not think I am doing (properly/at all).
the background Worker thread, UploadWorker, is constructed by passing in the a JProgressBar created in the main program, and sets changes the value of the progress bar directly once it is finished:
// when constructed, this gets set to the main program's JProgressBar.
JProgressBar progress;
protected Void doInBackground() throws Exception {
write("<!-- Import starting at " + getCurrentTime() + " -->\n");
boolean chunked = false;
switch (importMethod) {
//do some importing
}
write("<!-- Import attempt completed at " + getCurrentTime() + "-->\n");
//here changes to the GUI are made
progress.setMaximum(0);
progress.setIndeterminate(false);
progress.setString("Finished Working");
return null;
}
This works fine, but sometimes(not always) throws me several NPE's in the std out, and users are complaining:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.plaf.basic.BasicProgressBarUI.updateSizes(Unknown Source)
...etc...
Anyway, I believe there is something I need to do to get these updates executed on the proper thread, correct? How?
There are a number of ways you could do this, you could use the
process
method of theSwingWorker
to also update the progress bar, but for me, this couples your worker to the UI, which isn't always desirable.A better solution is to take advantage of the
SwingWorker
s progress andPropertyChange
support, for example....This means you could do this for ANY
SwingWorker
, so long as it was the worker was callingsetProgress
internally...The benefit of this is that the
PropertyChange
event notification is called from within the context of the of Event Dispatching Thread, making it safe to update the UI from within.And fully runnable example...
You can just create a new Runnable that performs GUI updates and invoke it in a GUI thread using SwingUtilities.invokeLater