InfiniteProgressPanel inside a Netbeans RCP TopComponent
January 3rd, 2009Anyone doing some serious work with Swing must have heard about the SwingFX API. This API contains some mightily cool GUI hacks, and I am particularly fond of Romain Guy’s infinite progress panel. So as a naive Java, Swing, NetBeans RCP programmer, I set out to use InfiniteProgressPanel to decorate the lenghty operations in my thesis project, AgentSpotter, the profiler for the MASs. Unsurprisingly, it did not work out of the box and required some understanding of the UI threading issues in Java, notably because I was working inside a NetBeans RCP TopComponent. In the end I managed to get the progress panel to work correctly, and I have encapsulated the logic in the following class:
public abstract class LenghtyOperationRunner
implements Runnable
{
Component _oldPane;
public LenghtyOperationRunner()
{
}
public void run()
{
startProgress();
Thread longOp = new Thread(new Runnable()
{
public void run()
{
doFirstPart();
SwingUtilities.invokeLater(
new Runnable()
{
public void run()
{
doFinalPart();
stopProgress();
}
});
}
});
longOp.start();
}
private void stopProgress()
{
final JFrame mainWin =
(JFrame) WindowManager.getDefault().getMainWindow();
final PerformanceInfiniteProgressPanel p =
(PerformanceInfiniteProgressPanel) mainWin.getGlassPane();
p.setVisible(false);
mainWin.setGlassPane(_oldPane);
}
private void startProgress()
{
final JFrame mainWin =
(JFrame) WindowManager.getDefault().getMainWindow();
_oldPane = mainWin.getGlassPane();
PerformanceInfiniteProgressPanel glassPane;
mainWin.setGlassPane(glassPane =
new PerformanceInfiniteProgressPanel());
glassPane.setVisible(true);
}
// Extension points:
// override these methods
// with the worker code
protected abstract void doFirstPart();
protected abstract void doFinalPart();
}
I have used PerformanceInfiniteProgressPanel, tweaked by Henry Story, instead of the standard InfiniteProgressPanel for performance reasons (would you expect something else from a profiling tool?). The implementation introduced by Romain in his original post was quite CPU intensive but it was subsquently improved by different SwingFX contributors.
The following code (adapted from here) shows how to use the class in a TopComponent:
class CallGraphTopComponent extends TopComponent {
private CallGraphTopComponent()
{
// This will launch the lenghty operation
SwingUtilities.invokeLater(new CallGraphLoader());
}
private class CallGraphLoader
extends LenghtyOperationRunner
{
JComponent treeview;
@Override
protected void doFirstPart()
{
// Start the main task here
final ProgressHandle progress =
ProgressHandleFactory.createHandle("Call Graph");
ProgressHandler progressHandler = new ProgressHandler()
{
... BLAH ...
};
// This is the lenghty operation
treeview = CallGraph.newInstance(progressHandler);
}
@Override
protected void doFinalPart() throws HeadlessException
{
// Things to run when the first part is finished
if (treeview == null)
JOptionPane.showMessageDialog(null,
"Cannot create call graph tree view.");
add(treeview);
}
}
}
To summarize, here are the steps to follow:
- Subclass the
LenghtyOperationRunnerclass listed here. - Override
doFirstPart()anddoFinalPart(). SwingUtilities.invokeLater()an instance of your custom runner wherever you want to display the progress panel while doing a lenghty operation. Et voilà!
Savvy readers will have noticed the use of SwingUtilities.invokeLater() which is the standard way to interact with the Java GUI event queue. The idea is to make sure that the main task code does not hog the CPU and leaves some breathing space for the UI thread which animates the panel. To this end, we must create a thread for the main task (doFirstPart()) which in turn must run any action that interacts with the UI in a new thread (doFinalPart()).
It must be noted that I tried to follow the steps described in this article first but it didn’t work for me. However you can still refer to this article to get more details on the mechanics of the progress panel.
Ultimately, I certainly have spent more time trying to make this panel work than I would have expected in the first place, but it was worth it because the bottom line is: the infinite progress panel is damn cool!
<french>
Le code présenté dans cet article décrit comment utiliser InfiniteProgressPanel dans une application NetBeans. Le secret est d’enchaîner correctement les appels à SwingUtilities.invokeLater() pour ne pas interférer avec le thread principal.
</french>






