2012-03-24 8 views
2

私がしようとしている:これは簡単であるべきJLabelの 奇妙なバグ - どのようにJavaプログラムを一時停止するには?

に新しいテキストを書き、その後2秒間、

  • ため

    1. 表示JLabelの中のテキスト、
    2. 待ちしかし、私は奇妙なバグを取得する: 最初のテキストは決して書かれていない、アプリケーションは2秒待ってから最終的なテキストを表示します。ここでのサンプルコードは、次のとおりです。このコードは、テキストと


      private void testButtonActionPerformed(java.awt.event.ActionEvent evt) {  
          displayLabel.setText("Clicked!"); 
      
          // first method with System timer 
      
          /* 
          long t0= System.currentTimeMillis(); 
          long t1= System.currentTimeMillis(); 
            do{ 
             t1 = System.currentTimeMillis(); 
            } 
            while ((t1 - t0) < (2000)); 
          */  
      
          // second method with thread.sleep() 
      
          try { 
           Thread.currentThread().sleep(2000); 
          } catch (InterruptedException e) {} 
      
          displayLabel.setText("STOP"); 
      } 
      

      「をクリック!」決して表示されません。私はちょうど2秒 - 一時停止し、次に "停止"テキストを取得します。 ループ、またはThread.sleep()でSystemタイマーを使用しようとしましたが、両方のメソッドで同じ結果が得られます。

  • +14

    (sigh)EDT(Event Dispatch Thread)をブロックしないでください。 'Thread.sleep(n)'を呼び出す代わりにSwingタイマーを実装するか、 'SwingWorker'を使って長時間実行するタスクを実行します。詳細は、[Swingの同時実行性](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/)を参照してください。 –

    答えて

    2

    Andrew Thompsonさんのコメントには、EDTがguiの更新を処理する責任があります。 Thread.sleep(...)を使用してブロックすると、それらの更新もブロックされます。そのため、最初のテキストは表示されません。EDTはラベルの更新を実行できません。

    2

    あなたが行っていることを実行する実行可能な例です。 Andrew Thompsonのコメントによれば、SwingWorkerはこの問題にアプローチする良い方法です。

    基本プリンシパルは、イベントディスパッチスレッドを決してブロックしません。それはGUIを再描画してユーザーのやりとりに応答するスレッドなので、EDTで計算コストが高いものを実行すると、GUIが応答を停止します。

    import java.awt.event.ActionEvent; 
    import java.awt.event.ActionListener; 
    import java.util.concurrent.ExecutionException; 
    
    import javax.swing.JButton; 
    import javax.swing.JFrame; 
    import javax.swing.SwingWorker; 
    
    public class ButtonTest { 
        public static void main(String[] args) { 
    
         // create a frame and a button 
         JFrame frame = new JFrame(); 
         final JButton button = new JButton("Button"); 
         frame.add(button); 
    
         // add an action listener to the button 
         button.addActionListener(new ActionListener() { 
    
          @Override 
          public void actionPerformed(ActionEvent arg0) { 
    
           // change the button text right away 
           button.setText("Clicked"); 
    
           // create a SwingWorker which simply waits 2000 milliseconds 
           // simulating a computation being performed 
           SwingWorker<String, Object> worker = new SwingWorker<String, Object>() { 
            @Override 
            public String doInBackground() { 
    
             // it's safe to call Thread.sleep() here 
             // doInBackground is executed on a separate worker 
             // thread 
             try { 
              Thread.sleep(2000); 
             } catch (InterruptedException e) { 
             } 
    
             return "Done"; 
            } 
    
            @Override 
            protected void done() { 
    
             // done() is executed back on the Swing thread 
             // so it's safe to updated the state of the button 
             try { 
              button.setText(get()); 
             } catch (Exception e) { } 
            } 
           }; 
    
           // run the worker 
           worker.execute(); 
          } 
         }); 
    
         frame.setSize(300, 300); 
         frame.setVisible(true); 
        } 
    } 
    
    +0

    アンドリュー・トンプソン、リングベアラー、ホバークラフト・フル・オブ・ウール、ulmangtに感謝します。最後に私はSwingWorkerを使って問題を解決しました。 – TerraNova993

    2

    あなたは、イベントディスパッチャスレッドを使いこなしています。 これは見た目に予想外のUI動作を引き起こします。 :以下curde-の例に示すように、スイングTimerを使用するFilthy rich clients

    より良い - あなたがアニメーションのこれらの種類を行うことを計画している場合は、@Andrewトンプソンが提案した内容にまで読んで、あなたがこれを読むことができる場合も、参照してください(はい、それは私がタイマーなどを停止する心配はありませんでした、粗製のです):

      @Override 
          public void actionPerformed(ActionEvent evt) { 
           if (i <= 1) { 
           messageLabel.setText(messages[i++]); 
           } else { 
           ((Timer)evt.getSource()).stop(); 
           } 
          } 
         }); 
    

    public class DelayTest extends JPanel{ 
        JLabel messageLabel = new JLabel(); 
        JButton actionButton = new JButton("Click Me"); 
        String[] messages = {"Clicked", "Stop!"}; 
        int i=0; 
        public DelayTest(){ 
         super(); 
         add(messageLabel); 
         add(actionButton); 
         actionButton.addActionListener(new ActionListener() { 
    
          @Override 
          public void actionPerformed(ActionEvent arg0) { 
           Timer timer = new Timer(1000, new ActionListener() { 
    
            @Override 
            public void actionPerformed(ActionEvent arg0) { 
             if(i<=1) 
              messageLabel.setText(messages[i++]); 
            } 
           }); 
           timer.start(); 
    
          } 
    
         }); 
        } 
    
    } 
    

    編集
    タイマーを停止しないのはなぜ

    +0

    @ TerraNova993これは最も簡単な方法です。スイングタイマーがある理由+1 – mKorbel

    +0

    タイマーを停止するコードを追加するときは?編集時にコードが追加されました。 –

    +0

    @HovercraftFullOfEels - それはできません - 私の例で言及しました。私は、テーラではなく、基本的なことを理解して正しく理解してほしいと思っています。編集中に –

    関連する問題