7

私はSwing、スレッド、invokeLater()、SwingWorkerなどについてたくさんのことを読んできましたが、私はすべてのことを考えているようには見えないので、説明するためのとても簡単なプログラムを作成しようとしていました。私は多くの例を見てきましたが、どれも私がしようとしていることを示すものではありません。私がJavaでプログラミングして以来、長い時間が経っています(2003年に高等学校でAPコンピュータサイエンスを受講して以来、私はJavaで何もしていませんでした)ので、私と一緒に裸にしてください。EDT以外でSwingコンポーネントを更新していますか?

私の例では何をしようとしています。ボタンとラベルがあります。ボタンをクリックすると、ラベルのテキストにピリオドを追加する前に、プログラムを3秒間一時停止します。その3秒間に、GUIを通常どおりに表示させ、追加のクリックに応答してください。

import javax.swing.SwingWorker; 

public class NewJFrame extends javax.swing.JFrame 
{ 
    private javax.swing.JButton jButton1; 
    private javax.swing.JLabel jLabel1; 

    public NewJFrame() 
    { 
     initComponents(); 
    } 
    private void initComponents() 
    { 
     jButton1 = new javax.swing.JButton(); 
     jLabel1 = new javax.swing.JLabel(); 
     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
     jButton1.setText("Button"); 
     jButton1.addActionListener(new java.awt.event.ActionListener() 
     { 
      public void actionPerformed(java.awt.event.ActionEvent evt) 
      { 
       jButton1ActionPerformed(evt); 
      } 
     }); 
     getContentPane().add(jButton1, java.awt.BorderLayout.CENTER); 
     jLabel1.setText("Text"); 
     getContentPane().add(jLabel1, java.awt.BorderLayout.PAGE_END); 
     pack(); 
    } 

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) 
    { 
     SwingWorker worker=new SwingWorker() 
     { 
      protected Object doInBackground() 
      { 
       try{Thread.sleep(3000);} 
       catch (InterruptedException ex){} 
       return null; 
      } 
     }; 
     worker.execute(); 
     jLabel1.setText(jLabel1.getText()+"."); 
    } 

    public static void main(String args[]) 
    { 
     java.awt.EventQueue.invokeLater(new Runnable() 
     { 
      public void run(){ new NewJFrame().setVisible(true); } 
     }); 
    } 
} 

このコードで、私はボタンをクリックした場合、私はEDTを残し、バックグラウンドスレッドを作成して寝ていますので、期間はすぐに、私には理にかなってラベルに追加されます:ここで私が書いたものですすぐにラベルを更新することができます。だから私はこれを試してみました:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) 
{ 
    Thread thread = new Thread(); 
    try{ thread.sleep(3000);} 
    catch (InterruptedException ex){} 
    jLabel1.setText(jLabel1.getText()+"."); 
} 

をこれはほとんどがブロックEDTボタンは、ラベルのテキストにピリオドを追加する前に、3秒間青色にさせることを除いて動作します。私はそれが本当にちょうどすぐにクリックされたとき、それは全体の3秒間押されているように、ボタンが見えるようにしたくないので、私はこれを試してみました:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) 
{ 
    SwingWorker worker=new SwingWorker() 
    { 
     protected Object doInBackground() 
     { 
      try{Thread.sleep(3000);} 
      catch (InterruptedException ex){} 
      jLabel1.setText(jLabel1.getText()+"."); 
      return null; 
     } 
    }; 
    worker.execute(); 
} 

これが動作しているように見えますが、私はjLabel1をを呼び出していません.setText(...)はバックグラウンドスレッドではなくEDTであるため、 "Swing Single Threading Rule?"もしそうなら、望ましい効果を達成するための良い方法がありますか?それ以外の場合は、理由を説明してください。

+2

+1努力と研究のために! – MadProgrammer

答えて

4

あなたは本当に近いです...

ではなく、このような何かを試してみてください。

SwingWorker worker=new SwingWorker() 
{ 
    protected Object doInBackground() 
    { 
     try{ 
      Thread.sleep(3000); 
     }catch (InterruptedException ex){} 
     return null; 
    } 

    // This is executed within the context of the EDT AFTER the worker has completed...  
    public void done() { 
     jLabel1.setText(jLabel1.getText()+"."); 
    } 
}; 
worker.execute(); 
、あなたがまた、より簡単かもしれない javax.swing.Timerを使用することができます

更新EventQueue.isDispatchingThread()

を使用して、EDTで実行しているかどうかを確認することができます

...

Timer timer = new Timer(3000, new ActionListener() { 
    public void actionPerformed(ActionEvent evt) { 
     jLabel1.setText(jLabel1.getText()+"."); 
    } 
}); 
timer.setRepeats(false); 
timer.start(); 
+0

迅速かつ簡潔な回答ありがとう!そのdone()メソッドは、私が探していたものとまったく同じです。タイマーもかなりいいですね。 –

+0

本当に良いと思った質問をお寄せいただきありがとうございます! – MadProgrammer

関連する問題