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);
          }
       }
 }

共有キューを持つ 2 つのクラスがあります。それらの1つは、ターゲットがそれらの要素を消費するまで生成するプロデューサーです。2 つすべてがスレッドを拡張します。進捗率をユーザーに表示したいのですが、GUI がフリーズします。どうすればよいですか?

4

2 に答える 2

6

while ループ全体をスレッドに入れる必要があると思います。そうしないと、ループによって ActionEvent がブロックされ、UI がフリーズします。

何かのようなもの:

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();
于 2012-11-24T17:57:14.083 に答える
6
  • Worker Threadsデフォルトでは呼び出されないためEventDispatchThread、問題がありますConcurency in Swing

  • Swing GUI の更新はすべて EDT で行う必要があります

  • Runnable適切な方法である可能性がProgressPrecent.setValue(Producer.ProgressPercent);ありますが、ラップする必要がありますinvokeLater

コード

SwingUtilities.invokeLater(new Runnable(){
    public void run(){
        ProgressPrecent.setValue(Producer.ProgressPercent);
    }
}); 
  • EDTのテストを削除し、

コード行

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

Workers Threadデフォルトでは、EDT を呼び出すことはありません。EDT から開始されても、テストしisDispatchThread()ても意味がありません。

  • Swing GUI もフリーズするため、Thread.sleep(int内部で )を使用しないでください。Swing Listeners

  • この作業にもSwingWorkerを使用できると思います

于 2012-11-24T18:25:51.177 に答える