Reputation: 759
I'm attempting to add a fancy InfiniteProgressPanel as a GlassPane for my big Swing program. However, it does not appear. It looks similar to this:
...
InfiniteProgressPanel glassPane = new InfiniteProgressPanel();
setGlassPane(glassPane);
...
glassPane.start();
doSomeStuff();
glassPane.stop();
...
I believe it is running in the same thread as the long process it is meant to cover up. I'll admit, I don't know nearly enough about threads, and I should probably figure out how to run that InfiniteProgressPanel GlassPane in a separate thread, and the long process in its own thread, too.
Upvotes: 1
Views: 1293
Reputation: 285403
Be sure to:
Run all long running code in a background thread. This is a must.
Sounds great! How do I do so? Encapsulate all of the long-running code inside of an .invokeLater method? And should that be SwingUtilities.invokeLater or EventQueue.invokeLater? And what's the difference, anyway?
SwingUtilities.invokeLater(new MyRunnable)
you're doing exactly the opposite -- you're guaranteeing that the long-running code will be called on the Swing event thread -- the exact opposite of what you want. Instead use a SwingWorker's doInBackground()
method to run the long-running code. Regarding your second point, there's no difference whatsoever between SwingUtilities.invokeLater
and EventQueue.invokeLater
.Make most all Swing calls on the Swing event thread, also a must.
Fantastic! Again, how do I do so? Same thing as above?
SwingUtilities.invokeLater(new MyRunnable)
as noted above, or if you're using a SwingWorker then use its publish/process method pair as the SwingWorker tutorial will show you.Call setVisible(true)
on your glass pane since per the JRootPane API, all glasspanes are by default invisible.
Romain Guy's InfiniteProgressPanel doesn't seem to need a setVisible(true). It appears when the InfiniteProgressPanel.start() method is called.
Upvotes: 4
Reputation: 480
Threads are different processes in the same program, per se.
In java, there are many different thread types, and the one you need for this job is SwingWorker
.
The definition/use of this, from Oracle's docs, is:
When a Swing program needs to execute a long-running task, it usually uses one of the worker threads, also known as the background threads. Each task running on a worker thread is represented by an instance of javax.swing.SwingWorker. SwingWorker itself is an abstract class; you must define a subclass in order to create a SwingWorker object; anonymous inner classes are often useful for creating very simple SwingWorker objects.
As you can see, this is what you need; a background thread.
final InfiniteProgressPanel glassPane;
...
class GlassPaneHandler extends SwingWorker<String, Object> {
@Override
public String doInBackground() {
glassPane.start();
return setUpPaneAndStuff();
}
@Override
protected void done() {
try {
glassPane.stop();
} catch (Exception e) { } //ignore
}
private void setUpPaneAndStuff() {
//code
}
}
...
(new GlassPaneHandler()).execute(); //place this in your code where you want to initiate the pane
for more see:http://docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html
Upvotes: 2
Reputation: 405
When you are updating a swing UI you need to do it in Swing's Event Thread. This includes creation of components or any sort of progress updates. You can do this via the SwingUtilities.invokeLater(Runnable) method.
Therefore, you should create the glasspane and show it via the invokeLater if in a background thread. Any progress updates to the glasspane from your long running process thread should be done via the invokeLater.
Upvotes: 1