jkteater
jkteater

Reputation: 1391

ProgressMonitorDialog - Watching active thread to update monitor

In my GUI I have a PDF file creation operation. The operation can take up to 10-15 seconds to complete. When I start the operation, I attach a listener to it. The listener changes the cursor and disables the GUI, until the operation completes.
I would also like to add a progressbar, so the users will have a idea when it is going to complete.

Created a method startProgressBar() and called it from the start of the operation method.
See Below:

  private void startSavePdfOperation() {
      startProgressBar();
      saveOp = new AplotSaveOperation(appReg.getString("aplot.message.SAVETOPDF"), "PDF", session);
      saveOp.addOperationListener(new MyOperationListener(this) {

startProgressBar Method - See Below:

 public void startProgressBar() {
     Shell shell = new Shell(getShell());
  shell.setSize(260, 120);
  final ProgressBar bar = new ProgressBar(shell, SWT.SMOOTH);
  bar.setBounds (20, 20, 200, 20);
  shell.open();
  final int maximum = bar.getMaximum();
  new Thread(new Runnable() {
     public void run() {
        for (final int[] i = new int[1]; i[0] <= maximum; i[0]++) {
        try {Thread.sleep (100);} catch (Throwable th) {}
           if (Display.getDefault().isDisposed()) return;
           Display.getDefault().asyncExec(new Runnable() {
              public void run() {
              if (bar.isDisposed ()) return;
                 bar.setSelection(i[0]);
              }
           });
        }
     }
  }).start();

The code above created the ProgressBar. The issue is that the operation would end well before the progressbar indicator was close to ending.

Question: Is this because in the method I am creating a new thread and the indicator is updating according to the new thread and not the operation thread?

Question: Is it possible to create a new thread that watches the GUI thread and updates the progressbar accordingly?

Read a article suggesting using ProgressMonitorDialog with IRunnableWithProgress.

Method startProgressBar using ProgressMonitorDialog - see below:

 public void startProgressBar() {
  ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());    
  try {
     dialog.run(true, true, new IRunnableWithProgress(){
          public void run(IProgressMonitor monitor) {
              monitor.beginTask("Some nice progress message here ...", 100);
              ** getThread(); **
              monitor.done();
          }
      });
  }
  catch (InvocationTargetException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
  }
  catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
  } 
}

 public void getThread() {
   new Thread etc.. etc...

 }

It seems that it will have the same issues with threading and updating as the code above.

Question: So now I am thinking can I just add or update the ProgressBar to my existing Listener

OperationListener Code - see below:

 public abstract class MyOperationListener implements InterfaceAIFOperationListener {
  AplotCreatePDFDialog w = null;

  public MyOperationListener(AplotCreatePDFDialog win) {
     w = win;
  } 
  public void startOperation(String startMessage) {
     Display.getDefault().asyncExec(new Runnable() {
        public void run() {
           w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_WAIT));
           w.recursiveSetEnabled(getShell(), getShell().getEnabled());
           w.getShell().setEnabled(!getShell().getEnabled());
        }
     });
  } 

  public void endOperation() {
     try {
        endOperationImpl();
     }
     finally {
        Display.getDefault().asyncExec(new Runnable() {
           public void run() {
              w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_ARROW));
              w.recursiveSetEnabled(getShell(), true);
              w.getShell().setEnabled(!getShell().getEnabled());
              w.close();
           }
        });
     }
  } 
  abstract protected void endOperationImpl();
} // end class MyOperationListener

Thanks for any help you can give me with this.

EDIT

Baz, your answer below is exactly what the question asked, so thank you for answering.

But I am starting to think that what I am trying to do is not possible. When my operation starts, I wanted the progress bar indicator to start and when my operation ended I wanted the indicator be at the end and the monitor would close.

I thought there might bee a way to use my listener to add the progressbar. Something like the following.

 public void startOperation(String startMessage) {
     Display.getDefault().asyncExec(new Runnable() {
        public void run() {
           ->monitor.beginTask("Creating PDF File(s)", IProgressMonitor.UNKNOWN);<-
           w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_WAIT));
           w.recursiveSetEnabled(getShell(), getShell().getEnabled());
           w.getShell().setEnabled(!getShell().getEnabled());

        }
     });
  } 
  public void endOperation() {
     try {
        ->monitor.worked(1);<-
        endOperationImpl();
     }
     finally {
        Display.getDefault().asyncExec(new Runnable() {
           public void run() {
              w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_ARROW));
              w.recursiveSetEnabled(getShell(), true);
              w.getShell().setEnabled(!getShell().getEnabled());
              ->monitor.done();<-
              w.close();
           }
        });
     }
  } 
  abstract protected void endOperationImpl();

} // end class MyOperationListener

But I am starting to see that the ProgressBar has to have some sort of measurement to display the indicator correctly.

I would be happy if the indicator just went back and forth and the monitor would close at the end of the operation.

Upvotes: 2

Views: 1782

Answers (1)

Baz
Baz

Reputation: 36894

Why not use ProgressMonitorDialog?

Here is a related answer from me showing a simple example.

This is what it looks like:

enter image description here


If you are not sure about the workload, use this code:

monitor.beginTask("Copying files", IProgressMonitor.UNKNOWN);

It will show the idle bar while running.

Upvotes: 2

Related Questions