user523956
user523956

Reputation: 521

Progressbar with SWT

I have tried to add progress bar in status line of the window, where there are already many text items on status line (for e.g. current time). I want to make progress in progressbar while loading data to one of the frame (called data) of the window. I have few problems regarding this. (I am quite new to SWT, so kindly bear with me.)

in makeProgress method I try to make progress in progress bar. Following is my code

public class Progress extends ContributionItem {

    private static org.eclipse.swt.widgets.ProgressBar progressBar;

    public Progress(final String id) {
        super(id);
    }

    @Override
    public void fill(final Composite parent) {
        if (progressBar == null) {
            progressBar = new ProgressBar(parent, SWT.None);
        }
        progressBar.setVisible(false);
    }

    public void makeProgress(final int loaded_data, final int total_data) {
        logger.log("progressitem do progress", new String [] {""});
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                Progress.progressBar.setVisible(true);
                Progress.progressBar.setMaximum(total_data);
                Progress.progressBar.setSelection(loaded_data);
            }});
        if (loaded_data == total_data) {
            //When all of the data are loaded, make progress bar disappear
            Display.getDefault().asyncExec(new Runnable() {
                public void run() {
                    Progress.progressBar.setVisible(false);
                }});
        }
    }
}

where makeProgress called by a class which handles statusbar like following: change is a type of

if (change.getChange() == hasChanged.UPDATE_PROGRESS) {
            progress.makeProgress(change.getLoaded_data(), change.getTotal_data);

Problems:

1) My progress bar is progressing very slow. May be proper use of threads required ?

2) Although I tried, I am not quite clear with the difference between Display.getDefault.asyncExec and syncExec.

3) Another issue is, when progress bar is progressing, The whole GUI is not responsive. How can I make progressbar independent of other views on the GUI ?

I would really appreciate any pointers or suggestions regarding this.

Upvotes: 0

Views: 8255

Answers (4)

Kristen Gillard
Kristen Gillard

Reputation: 1

I use the following implementation to add a progress bar to the status line contribution item:

try {
    /** launch the progress monitor that is reading the image file */
    ModalContext.run( new IRunnableWithProgress( )
    {
        @Override
        public void run(IProgressMonitor progressMonitor)
        {
            progressMonitor.beginTask( "Reading: " + filename, IProgressMonitor.UNKNOWN );
            manager.read( filename );
            progressMonitor.done( );
        }
    }, true, getStatusLineManager( ).getProgressMonitor( ),   Display.getDefault( ) );
} catch (MyException e)
{
   throw new Error("An error occurred updating the component.", e);
}

Upvotes: 0

Lasan
Lasan

Reputation: 183

I would like to answer for your questions

1) My progress bar is progressing very slow. May be proper use of threads required ? Yes you need to manage them .

2) Although I tried, I am not quite clear with the difference between Display.getDefault.asyncExec and syncExec. syncExec work one after another where asyncExec work parallel way

3) Another issue is, when progress bar is progressing, The whole GUI is not responsive. How can I make progressbar independent of other views on the GUI ?

Check following code, how to do this. fully functional

public static void main(String[] args) {
    Display display = new Display();
    Shell baseComposit = new Shell(display);
    RowLayout layout = new RowLayout();
    layout.type = SWT.VERTICAL;
    baseComposit.setLayout(layout);
    ProgressBar bar = new ProgressBar(baseComposit, SWT.None);
    bar.setLayoutData(new RowData(1000, 25));
    Text helloWorldTest = new Text(baseComposit, SWT.NONE);
    helloWorldTest.setLayoutData(new RowData(500, 25));
    helloWorldTest.pack();
    Button button = new Button(baseComposit, SWT.NONE);
    button.setText("START");
    button.setLayoutData(new RowData(50, 40));
    button.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            bar.setMaximum(10000);

            for (int i = 1; i < 10000; i++) {
                int count = i;
                bar.getDisplay().asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        bar.setSelection(count);
                        try {
                            Thread.sleep(2);
                        } catch (InterruptedException e) {

                            e.printStackTrace();
                        }

                    }
                });
                helloWorldTest.getDisplay().asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        helloWorldTest.setText(Integer.toString(count));

                    }
                });

            }

        }

    });
    Button clear = new Button(baseComposit, SWT.VERTICAL);
    clear.setText("CLEAR");
    clear.setLayoutData(new RowData(50, 40));
    clear.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            bar.setSelection(0);
            helloWorldTest.setText("");
        }

    });
    baseComposit.open();
    while (!baseComposit.isDisposed()) {
        if (!display.readAndDispatch())
            display.sleep();
    }
    display.dispose();

}

Upvotes: 0

Don Miller
Don Miller

Reputation: 1

I wanted to post this example of adding a progress bar to an existing composite. All of the examples I see start with a new shell and main function.

public class MainScaleComposite extends Composite {
    public boolean calStarted=false;
    public boolean calFinished=false;

public MainScaleComposite(Shell parent, int style) {
    super(parent,style);    
    log = Logger.getLogger(MainScaleComposite.class.getName()); // get the logger for this class


private void startCalThread(){
    final StringBuffer sb = new StringBuffer("");


    if (calStarted==false){
       new Thread(new Runnable()
       {


          @Override
          public void run()
          {
              try
                {
                     calStarted=true;
                    append(sb,service.ExecuteCommand.executeProcess("<<your program here>>",0,null));
                    calFinished=true;
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }



         }

      }).start();
    }
}
private void StartTimer(){
    final Display display = this.getDisplay();

    final ProgressBar bar = new ProgressBar (this, SWT.SMOOTH);
    bar.setBounds (300, 170, 200, 32);


    display.timerExec(100, new Runnable() {
        int i = 0;
        @Override
        public void run() {
            if (bar.isDisposed()) return;
            bar.setSelection(i++);
            if (i < bar.getMaximum()) display.timerExec(100, this);

        }
    });
    startCalThread();
    while (!calFinished) {
        if (!display.readAndDispatch ()) display.sleep ();
    }

}

Upvotes: 0

Baz
Baz

Reputation: 36894

Ok, here is a simple example with a ProgressBar that's updated continuously from another thread. The GUI is still responsive throughout:

private static Shell        shell;
private static ProgressBar  progressBar;

public static void main(String[] args)
{
    Display display = new Display();
    shell = new Shell(SWT.SHELL_TRIM);
    shell.setText("StackOverflow");
    shell.setLayout(new GridLayout(1, false));

    setUpContent();
    setUpStatusBar();

    updateProgressBar();

    shell.pack();
    shell.setSize(400, 200);
    shell.open();

    while (!shell.isDisposed())
    {
        if (!display.readAndDispatch())
        {
            display.sleep();
        }
    }
    display.dispose();
}

private static void updateProgressBar()
{
    new Thread(new Runnable()
    {
        private int                 progress    = 0;
        private static final int    INCREMENT   = 10;

        @Override
        public void run()
        {
            while (!progressBar.isDisposed())
            {
                Display.getDefault().asyncExec(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        if (!progressBar.isDisposed())
                            progressBar.setSelection((progress += INCREMENT) % (progressBar.getMaximum() + INCREMENT));
                    }
                });

                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }).start();
}

private static void setUpStatusBar()
{
    Composite statusBar = new Composite(shell, SWT.BORDER);
    statusBar.setLayout(new GridLayout(2, false));
    statusBar.setLayoutData(new GridData(SWT.FILL, SWT.END, true, false));

    progressBar = new ProgressBar(statusBar, SWT.SMOOTH);
    progressBar.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false));
    progressBar.setMaximum(100);

    Label status = new Label(statusBar, SWT.NONE);
    status.setText("Some status message");
    status.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, false));
}

private static void setUpContent()
{
    Composite content = new Composite(shell, SWT.NONE);
    content.setLayout(new GridLayout(2, false));
    content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    Text text = new Text(content, SWT.BORDER | SWT.MULTI);
    text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
}

My guess why your application freezes and the progress isn't updated smoothly is that it's doing heavy computational / long running tasks on the main thread instead of a separate thread.

Upvotes: 3

Related Questions