3
 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?

morja
  • 8,297
  • 2
  • 39
  • 59
Alyafey
  • 1,455
  • 3
  • 15
  • 23
  • try using `SwingUtilities.invokeLater(new Runnable())` – devsnd Nov 24 '12 at 17:01
  • I did it but it also won't work? – Alyafey Nov 24 '12 at 17:03
  • Well, you will have to be more specific if you need help. You might also want to improve your question to explain your code. Reading the FAQ will help you. – devsnd Nov 24 '12 at 17:05
  • 2
    @sarcan: Not everybody speaks/writes english as their mothertongue. You should not discriminate someone because of language, since it isn't the actual problem. It's about explaining what has been tried etc... – devsnd Nov 24 '12 at 17:07
  • I had this problem in C# but it solve, you can see the question here http://stackoverflow.com/questions/13141280/updating-progress-bar-from-thread-in-c-sharp – Alyafey Nov 24 '12 at 17:14
  • Several useful examples are cited in the [answers to this question](http://stackoverflow.com/q/13538275/230513). – trashgod Nov 24 '12 at 18:20

2 Answers2

6

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();
morja
  • 8,297
  • 2
  • 39
  • 59
  • 1
    How will you synchronize access to `ProgressPrecent`? – trashgod Nov 24 '12 at 18:21
  • Just tried to point out that the loop will cause the initial event to block. Updated my answer. – morja Nov 24 '12 at 18:36
  • Without knowing otherwise, it would be dangerous to call `ProgressPrecent.setValue` - All UI updates MUST be executed within the Event Dispatching Thread - While in theory your answer is correct, is misleading and will end in "why do I get paint artifices" questions, followed "but I was told to" answers ... – MadProgrammer Nov 24 '12 at 20:39
6
  • 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

Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319