2017-11-21 4 views
0

performActionメソッドでいくつかの操作を行うスイングアプリケーションを作成しましたが、progressBarを示すスレッドを作成すると、progressActionメソッドの実行中にprogressBarが表示されませんが、最後にprogressBarは100%直接
メインクラス:スイングでactionPerformed内に新しいスレッドを作成するのは安全ですか?

import javax.swing.*; 
    import javax.swing.plaf.ButtonUI; 
    import java.awt.*; 
    import java.awt.event.ActionEvent; 
    import java.awt.event.ActionListener; 

public class main { 
    public static void main(String[] args) { 
     JFrame win = new JFrame("Test"); 
     FlowLayout layout = new FlowLayout(); 
     Button b1 = new Button("Click "); 
     win.add(b1); 
     b1.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       window win = new window(); 
       win.start(); 
       try 
       { 
        Thread.sleep(2000); 
       } 
       catch(InterruptedException e5){} 
      } 
     }); 
     win.setLayout(layout); 
     win.setSize(500, 300); 
     win.setLocationRelativeTo(null); 
     win.setVisible(true); 
     win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    } 
} 

ウィンドウクラス:

import javax.swing.*; 
import java.awt.*; 

public class window extends Thread{ 
    public window(){ 

    } 

    @Override 
    public void run() { 
     JFrame fen = new JFrame("New window"); 
     FlowLayout layout = new FlowLayout(); 
     fen.setLayout(layout); 
     Button b2 = new Button(); 
     fen.setVisible(true); 
     fen.setSize(100, 100); 
     fen.setLocationRelativeTo(null); 
     fen.add(b2); 
     try 
     { 
      for(int i = 0; i <= 100; i++) 
      { 
       b2.setLabel("Button " + i); 
       Thread.sleep(10); 
      } 
     } 
     catch(InterruptedException e2){ 

     } 
    } 
} 
+1

これはすべて間違っています。スイング同時実行チュートリアル(https://docs.oracle.com/javase/tutorial/uiswing/concurrency/)を読んでください。そして、Javaの命名規則を尊重してください。 –

答えて

3

はい、新しいを作成しても安全ですThreadactionPerformedハンドラの内部にあります。

しかし、イベントディスパッチスレッド(EDT)以外のスレッドは、Swingコンポーネントと対話していない必要があります。

アニメーションを作成する、またはSwing内で遅延させるには、javax.swing.Timerを使用する必要があります。 EDTにThread.sleep()を実行することは決して許されず、望むことを望んでいません。

スポーンされたスレッドからEDTに戻るには、SwingUtilities.invokeLater()またはSwingUtilities.invokeAndWait()を使用する必要があります。

スイングでバックグラウンドタスクを実行するには、SwingWorkerを使用するのが好ましい方法です。 GUIコンポーネントに表示するためのバックグラウンドタスクからEDTへの部分的および最終的な結果の通信および公開を処理します。次


SwingWorkerを使用して、実施例にあなたのコードの翻訳です。 AWT Buttonの代わりに、Swing JButtonが使用されます。プログラムは、invokeAndWaitを使用して作成され、EDT上でメインウィンドウの構成が確実に行われます。ラムダ関数が使用されますが、必要に応じてこれをnew Runnable() { }内部クラスに置き換えることができます。 「ボタン0」から「ボタン100」の進捗レポートは、EDTでの処理のために、バックグラウンドタスクから公開されています。 EDTがそれらを処理する機会を得る前に、バックグラウンドスレッドによって複数の結果を生成することができます。ここでは、ボタンに表示する最後の結果のみを取ります。

public class Main { 

    public static void main(String[] args) throws Exception { 
     SwingUtilities.invokeAndWait(() -> { 
      JFrame win = new JFrame("Test"); 
      win.setLayout(new FlowLayout()); 
      JButton b1 = new JButton("Click"); 
      b1.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent ae) { 
        DoWork work = new DoWork(); 
        work.execute(); 
       } 
      }); 
      win.add(b1); 
      win.setSize(500, 300); 
      win.setLocationRelativeTo(null); 
      win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      win.setVisible(true); 
     }); 
    } 
} 

class DoWork extends SwingWorker<Void, String> { 
    JFrame fen; 
    JButton b2; 

    DoWork() { 
     fen = new JFrame("New window"); 
     fen.setLayout(new FlowLayout()); 
     b2 = new JButton(); 
     fen.add(b2); 
     fen.setSize(100, 100); 
     fen.setLocationRelativeTo(null); 
     fen.setVisible(true); 
     fen.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
    } 

    @Override 
    protected Void doInBackground() throws Exception { 
     for (int i = 0; i <= 100; i++) { 
      publish("Button " + i); 
      Thread.sleep(10); 
     } 
     return null; 
    } 

    @Override 
    protected void process(List<String> data) { 
     String last = data.get(data.size() - 1); 
     b2.setText(last); 
    } 

    @Override 
    protected void done() { 
     fen.dispose(); 
    } 
} 

このコードにはまだいくつかの改善点があります。結果を表示するためのJButtonの代わりにJLabel、進捗ウィンドウのJDialog、またはおそらくはProgressMonitorがあります。これらは学生に運動として残されています。

関連する問題