In the last tip, I said the top most mistake done by Eclipse plug-in developers is running long running operations in the UI thread. Assuming that you are running it in a non-UI thread, how to show the progress of the execution? Obviously thru progress monitors. But how many different ways are there to show a progress monitor? Lets see them in this tip.
The first option is ProgressMonitorDialog. You have to create a IRunnableWithProgress and use the run method:
ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
dialog.run(true, true, new IRunnableWithProgress(){
public void run(IProgressMonitor monitor) {
monitor.beginTask("Some nice progress message here ...", 100);
// execute the task ...
monitor.done();
}
});
Result:
As you can see, the dialog is kind-of blocking the user. This dialog is advisable only in the rare cases where the user have to wait till the operation is completed. In most other cases, you should prefer running a Job. A Job is not blocking to the user and can still show the progress. The progress is available in the Progress View.
Job job = new Job("My new job") {
@Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask("Some nice progress message here ...", 100);
// execute the task ...
monitor.done();
return Status.OK_STATUS;
}
};
job.schedule();
Result:

If you make the job as a user job by calling setUser(true), the progress dialog will be opened, where the user can chose to run the job as a background job. If the user doesn't want to see this dialog again, he can select to 'Always run in background':
When the job is initiated by the user interacting with a workbench part (like clicking a button in a view), a better way to schedule the job is thru the site's IWorkbencSiteProgressService.schedule. When the job begins to execute, the workbench part can show it visually. The default behaviour is to italize the part name:
But you can customize it by overriding the showBusy() method in your WorkbenchPart:
public void showBusy(boolean busy) {
super.showBusy(busy);
if(busy)
setPartName("I'm doing a job right now...");
else
setPartName("Sample View");
}
Result:
In case your action doesn't have any WorkbenchPart associated with it, you can use the IWorkbenchWindow.run(...) to show the progress:
If you are running a long running operation in a wizard/wizardPage you should consider running it thru getContainer().run(). This will show the progressBar right there in the wizard dialog itself:
If you are updating the UI elements in the wizardPage during the execution, you have to note that if you do a setEnabled() on any widget, it won't reflect. Its because the container registers the enabled state of the widgets before execution; disables the widgets; executes the task and restores the widget's enabled state to the saved value. So if you have changed the state during the operation, it will be overwritten by the container.
In case, you can't display a progressbar, you should at least use BusyIndicator.showWhile() and display the busy cursor to show that some operation is being executed. Else the user might be wondering why the UI is frozen.
Feb 12, 2009
Using progress bars ...
Prakash G.R.
Disclaimer
Any opinion expressed here, in any other blogs, forums, websites, "Letters to the Editor" column in "The Hindu" daily, weekly magazine’s sudoku column, my daughter’s drawing book and scribbling on the toilet papers, are not necessary my employers opinion, but all my own :-P
Unless specified, all the content of this blog is made available under Eclipse Public License
Unless specified, all the content of this blog is made available under Eclipse Public License
21 comments:
This is probably the most concise explanation of where and how to use progress services in eclipse I've seen.
I find there is a lot of separate doco on individual services and "things" in eclipse, but nothing that ties them all together to describing their usage patterns. (When to use X over Y).
Well done.
Awesome! It's nice to see such a concise post of how to implement a piece functionality and the different scenarios that apply. One of the best eclipse tips ever!
Hi Prakash,
the Tip seems to be cool and simple. The status line is not colored(green/blue) on my dialog. I don't know why. May you have an idea?! Please let me know. I definitely will use this code in my application.
Thanks,
Simpson
@Freaky-namuH and @sud,
Thanks. Will continue to write these kind of tips.
@Simpson,
Did you make any changes in the colors or themes in the Preferences?
Hello,
you wrote that it is possible to run the job via IWorkbenchWindow.run(). I like the look of this progress bar because the user can cancel the job without having a big window on top.
But I saw that the run-method takes only a IRunnableWithProgress and we are completely using the eclipse job framework.
Is there a way to show the job in the way you mentioned in the article?
Thanks,
Jens
@Jens,
Only IRunnableWithProgress can be run in a IRunnableContext - not Job. I don't think there is a direct way to do it. Making your job to implement IRunnableWithProgress also won't work, as the run method in both the places differ only by the return value - which is not allowed in Java.
In short, there might be a hack, but I don't know :-(
Hi Prakash,
thanks for answering my question about the color of the status line. All the preference settings are default. May be need enable/disable something!?!
Simpson
Great tip. Thanks a lot.
I made use of your tip today in my work . Thanks prakash
I am amazed! this is the most comprehensive yet concise, useful and to the point explanation of anything. thank you. this has saved me a lot of time and probably would have saved me the last 2 days if I had found this earlier. :)
Hi,
Is there a way to show animated gif as TitleImage while view is working?
@Kubu,
I don't think animated gif will work in the view's title image. You may have to cycle thru individual icons. Check Mylyn code, their editor seems to have that functionality
Thanks Prakash,
If I run the following lines of code in an editor:
this.miningJob = new MiningJob();
this.miningJob.setPriority(Job.LONG);
this.miningJob.setUser(true);
IWorkbenchSiteProgressService progressService = (IWorkbenchSiteProgressService)getSite().getService(IWorkbenchSiteProgressService.class);
progressService.schedule(this.miningJob);
the MiningJob will be scheduled and run, but nothing will appear in the status line. Do you know why ? Am I missing something ?
Damien
I found the problem. I had to add the following line to the contents of the method preWindowOpen() of my ApplicationWorkbenchWindowAdvisor:
configurer.setShowProgressIndicator(true);
Now I have another problem: nothing will happen when I click on the progress icon of the status line while the job is running. I was expecting the ProgressView to be brought to front, but I have to do that myself by clicking on the ProgressView tab :(.
Have you ever heard of that problem ?
Many thanks in advance,
Damien
Hi Prakash
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
try {
dialog.run(true, true, new IRunnableWithProgress(){
public void run(IProgressMonitor monitor) {
monitor.beginTask("Deployment in progress", 100);
// I want call a method (say Deployment) which takes lot of time( I dont know exactly how much)
// But it doesnt show me progress. Only i do call monitor.worked(work) it shows .
// but But that is not correct progress .. how to go abt ..
monitor.setTaskName("Deployment Completed.");
monitor.done();
}
});
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I dont how to go about
I have added the comments , problems
Regards
Govind
@Govind,
Try this:
monitor.beginTask("Deployment in progress", IProgressMonitor.Unknown);
Thanks a lot prakash... :)
One more thing is it possible remove the cancel button . ??
Thanks and Regards
Govind R Ashrit
@goivnd,
See: http://blog.eclipse-tips.com/2009/01/top-10-mistakes-in-eclipse-plug-in.html
What does run(true, true, ...) means ;-)
Hi Prakash..
i over looked that ..
Thanks a lot..
Hi Prakash
dialog.run(true, false, new IRunnableWithProgress(){
public void run(IProgressMonitor monitor) {
onitor.beginTask("Sync", 100);
monitor.beginTask(".Please wait...", IProgressMonitor.UNKNOWN);
table.getItems();
monitor.done();
}
});
When i do this i get
Caused by: org.eclipse.swt.SWTException: Invalid thread access
How can we acess other swt controls
Regards
Govind R
@Govind
It would be impossible for me to answer all the queries. You can check http://eclipse.org/forums for more help
Post a Comment