Alyafey
Alyafey

Reputation: 1453

How to update java GUI from Thread?

 private void StartActionPerformed(java.awt.event.ActionEvent evt) {

        Queue queue=new Queue();
        int target=Integer.parseInt(Target.getText());
        String path=Path.getText();
        final Producer p=new Producer(queue, target);
        Consumer c=new Consumer(queue);
        p.start();
        c.start();

        while(p.finish !=true)
        {
          Runnable r = new Runnable() {
            public void run() {
              ProgressPrecent.setValue(Producer.ProgressPercent);
            }
          };
          if(EventQueue.isDispatchThread()) {
            r.run();
          }
          else {
            EventQueue.invokeLater(r);
          }
       }
 }

I have two classes that have a shared Queue. one of them is Producer that produces till a target other one consume those elements. all of two extends Thread. I want to display the progress percent to the user, but it freeze my GUI so what should I do?

Upvotes: 3

Views: 12670

Answers (2)

morja
morja

Reputation: 8560

I think you will have to put the whole while loop into a thread. Otherwise the loop will block your ActionEvent and thus freezes the UI.

Something like:

new Thread(){
    public void run(){
        while(!p.finish){
           SwingUtilities.invokeLater(new Runnable(){
             public void run(){
               ProgressPrecent.setValue(Producer.ProgressPercent);
             }
           }); 
           try{
              Thread.sleep(100);
           }catch(...){}
        }
    }
}.start();

Upvotes: 6

mKorbel
mKorbel

Reputation: 109813

  • Worker Threads by default never to invoked EventDispatchThread, you have issue with Concurency in Swing

  • all updates to Swing GUI must be done on EDT

  • Runnable could be proper way but ProgressPrecent.setValue(Producer.ProgressPercent); must be wrapped in invokeLater

code

SwingUtilities.invokeLater(new Runnable(){
    public void run(){
        ProgressPrecent.setValue(Producer.ProgressPercent);
    }
}); 
  • remove testing for EDT,

code lines

if(EventQueue.isDispatchThread()) {
   r.run();
}

Workers Thread by defaut never ever to invoke EDT, then doesn't matter if is started from EDT, nor tested for isDispatchThread() doesn't make me some sence

  • never ever, don't to use Thread.sleep(int) inside Swing Listeners, because caused freeze Swing GUI too

  • I think you can to use SwingWorker for this job too

Upvotes: 6

Related Questions