Cancellable Tasks and Progress Indicators [Netbeans Platform]
Progress indicator (indeterminate mode) which allows to cancel the task
The easiest way of having a cancellable progress indicator (Progress API) for a task in Netbeans Platform Application is the one below but it’s only worth for tasks that don’t update the progress indicator (indeterminate mode) until the task is finished. If you want to update the progress indicator (ProgressHandle) inside the task itself look at the second example.
<span class='line'>package com.rubenlaguna.en4j.mainmodule;
</span><span class='line'>
</span><span class='line'>import java.awt.event.ActionEvent;
</span><span class='line'>import java.awt.event.ActionListener;
</span><span class='line'>import java.util.logging.Logger;
</span><span class='line'>import org.netbeans.api.progress.ProgressHandle;
</span><span class='line'>import org.netbeans.api.progress.ProgressHandleFactory;
</span><span class='line'>import org.openide.util.RequestProcessor;
</span><span class='line'>import org.openide.util.TaskListener;
</span><span class='line'>
</span><span class='line'>public final class MyCancellableActionNoProgressInformation implements ActionListener {
</span><span class='line'>
</span><span class='line'> //The RequestProcessor has to have allowInterrupt set to true!!
</span><span class='line'> private final static RequestProcessor RP = new RequestProcessor("interruptible tasks", 1, true);
</span><span class='line'> private final static Logger LOG = Logger.getLogger(MyCancellableActionNoProgressInformation.class.getName());
</span><span class='line'>
</span><span class='line'> public void actionPerformed(ActionEvent e) {
</span><span class='line'>
</span><span class='line'> Runnable runnable = new Runnable() {
</span><span class='line'>
</span><span class='line'> private final int NUM = 60000;
</span><span class='line'>
</span><span class='line'> public void run() {
</span><span class='line'> for (int i = 0; i < NUM; i++) {
</span><span class='line'> doSomething(i);
</span><span class='line'> if (Thread.interrupted()) {
</span><span class='line'> LOG.info("the task was CANCELLED");
</span><span class='line'> return;
</span><span class='line'> }
</span><span class='line'> }
</span><span class='line'>
</span><span class='line'> }
</span><span class='line'>
</span><span class='line'> private void doSomething(int i) {
</span><span class='line'> LOG.info("doSomething with " + i);
</span><span class='line'> return;
</span><span class='line'> }
</span><span class='line'> };
</span><span class='line'>
</span><span class='line'> final RequestProcessor.Task theTask = RP.create(runnable);
</span><span class='line'>
</span><span class='line'> final ProgressHandle ph = ProgressHandleFactory.createHandle("performing some task", theTask);
</span><span class='line'> theTask.addTaskListener(new TaskListener() {
</span><span class='line'> public void taskFinished(org.openide.util.Task task) {
</span><span class='line'> //make sure that we get rid of the ProgressHandle
</span><span class='line'> //when the task is finished
</span><span class='line'> ph.finish();
</span><span class='line'> }
</span><span class='line'> });
</span><span class='line'>
</span><span class='line'> //start the progresshandle the progress UI will show 500s after
</span><span class='line'> ph.start();
</span><span class='line'>
</span><span class='line'> //this actually start the task
</span><span class='line'> theTask.schedule(0);
</span><span class='line'> }
</span><span class='line'>}</span>
leads to
INFO [com.rubenlaguna.en4j.mainmodule.ImportEvernoteFile]: doSomething with 6619
INFO [com.rubenlaguna.en4j.mainmodule.ImportEvernoteFile]: doSomething with 6620
INFO [com.rubenlaguna.en4j.mainmodule.ImportEvernoteFile]: doSomething with 6621
INFO [com.rubenlaguna.en4j.mainmodule.ImportEvernoteFile]: doSomething with 6622
INFO [com.rubenlaguna.en4j.mainmodule.ImportEvernoteFile]: the task was CANCELLED
Progress indicator (determinate mode) which allows to cancel the task
This example show a ProgressHandle that it’s updated from the Runnable and it’s stil cancelable. In this case you are also somewhat to use the more cumbersome catch(InterruptedException) instead of just checking Thread.interrupted(). For some reason I couldn’t get the Thread.interrupted() to work in this case. Doing a Thread.sleep(0) will always throw a InterruptedException if the thread was interrupted (canceling a task will interrupt the thread if the RequestProcessor is created with the interruptThread=true).
<span class='line'>package com.rubenlaguna.en4j.mainmodule;
</span><span class='line'>
</span><span class='line'>import java.awt.event.ActionEvent;
</span><span class='line'>import java.awt.event.ActionListener;
</span><span class='line'>import java.util.logging.Logger;
</span><span class='line'>import org.netbeans.api.progress.ProgressHandle;
</span><span class='line'>import org.netbeans.api.progress.ProgressHandleFactory;
</span><span class='line'>import org.openide.util.Cancellable;
</span><span class='line'>import org.openide.util.RequestProcessor;
</span><span class='line'>import org.openide.util.Task;
</span><span class='line'>import org.openide.util.TaskListener;
</span><span class='line'>
</span><span class='line'>public final class MyCancellableAction implements ActionListener {
</span><span class='line'>
</span><span class='line'> private final static RequestProcessor RP = new RequestProcessor("interruptible tasks", 1, true);
</span><span class='line'> private final static Logger LOG = Logger.getLogger(MyCancellableAction.class.getName());
</span><span class='line'> private RequestProcessor.Task theTask = null;
</span><span class='line'>
</span><span class='line'> public void actionPerformed(ActionEvent e) {
</span><span class='line'> final ProgressHandle ph = ProgressHandleFactory.createHandle("task thats shows progress", new Cancellable() {
</span><span class='line'>
</span><span class='line'> public boolean cancel() {
</span><span class='line'> return handleCancel();
</span><span class='line'> }
</span><span class='line'> });
</span><span class='line'>
</span><span class='line'> Runnable runnable = new Runnable() {
</span><span class='line'>
</span><span class='line'> private final int NUM = 60000;
</span><span class='line'>
</span><span class='line'> public void run() {
</span><span class='line'> try {
</span><span class='line'> ph.start(); //we must start the PH before we swith to determinate
</span><span class='line'> ph.switchToDeterminate(NUM);
</span><span class='line'> for (int i = 0; i < NUM; i++) {
</span><span class='line'> doSomething(i);
</span><span class='line'> ph.progress(i);
</span><span class='line'> Thread.sleep(0); //throws InterruptedException is the task was cancelled
</span><span class='line'> }
</span><span class='line'>
</span><span class='line'> } catch (InterruptedException ex) {
</span><span class='line'> LOG.info("the task was CANCELLED");
</span><span class='line'> return;
</span><span class='line'> }
</span><span class='line'>
</span><span class='line'> }
</span><span class='line'>
</span><span class='line'> private void doSomething(int i) {
</span><span class='line'> LOG.info("doSomething with " + i);
</span><span class='line'> return;
</span><span class='line'> }
</span><span class='line'> };
</span><span class='line'>
</span><span class='line'> theTask = RP.create(runnable); //the task is not started yet
</span><span class='line'>
</span><span class='line'> theTask.addTaskListener(new TaskListener() {
</span><span class='line'> public void taskFinished(Task task) {
</span><span class='line'> ph.finish();
</span><span class='line'> }
</span><span class='line'> });
</span><span class='line'>
</span><span class='line'> theTask.schedule(0); //start the task
</span><span class='line'>
</span><span class='line'>
</span><span class='line'> }
</span><span class='line'>
</span><span class='line'> private boolean handleCancel() {
</span><span class='line'> LOG.info("handleCancel");
</span><span class='line'> if (null == theTask) {
</span><span class='line'> return false;
</span><span class='line'> }
</span><span class='line'>
</span><span class='line'> return theTask.cancel();
</span><span class='line'> }
</span><span class='line'>}</span>
leads to
INFO [com.rubenlaguna.en4j.mainmodule.MyCancellableAction]: doSomething with 5399
INFO [com.rubenlaguna.en4j.mainmodule.MyCancellableAction]: doSomething with 5400
INFO [com.rubenlaguna.en4j.mainmodule.MyCancellableAction]: doSomething with 5401
INFO [com.rubenlaguna.en4j.mainmodule.MyCancellableAction]: doSomething with 5402
INFO [com.rubenlaguna.en4j.mainmodule.MyCancellableAction]: doSomething with 5403
INFO [com.rubenlaguna.en4j.mainmodule.MyCancellableAction]: doSomething with 5404
INFO [com.rubenlaguna.en4j.mainmodule.MyCancellableAction]: doSomething with 5405
INFO [com.rubenlaguna.en4j.mainmodule.MyCancellableAction]: handleCancel
INFO [com.rubenlaguna.en4j.mainmodule.MyCancellableAction]: doSomething with 5406
INFO [com.rubenlaguna.en4j.mainmodule.MyCancellableAction]: the task was CANCELLED