程式扎記: [ Java 代碼範本 ] SwingWorker Example

標籤

2012年10月28日 星期日

[ Java 代碼範本 ] SwingWorker Example


來源自 這裡
Preface :
當我們開發 Swing 程式需要執行需耗時的工作時, 可以使用 worker thread (或稱為 background threads). 而這樣的 worker thread 可以使用類別 javax.swing.SwingWorker 來完成. 它是抽象類別, 要使用時可以繼承該類別, 並實作方法 doInBackground(), 並在裡面執行耗時工作.

Demo Code:
下面的範例代碼會建立一個 UI 如下:


點擊按鈕 "Start" 將會建立 NumberWorker 的物件, 它實作 javax.swing.SwingWorker, 接著會執行你實作方法 doInBackground() 的代碼, 而當背景程式正在執行時你可以任意移動該 UI, 甚至可以在 TextField 上面輸入字串; 而在你從該方法透出後, 方法 done() 會被執行:


而在背景程式 done() 方法中, 會將取得的 random number 設回原來 UI 的 TextField 並完成背景工作.


當你在點擊按鈕 "Start" 後, 按鈕 "Cancel" 將會被 enable. 當你點擊 "Cancel" 按鈕, 在 "Start" 按鈕點擊後建立的 NumberWorker 的物件上的方法 cancel(true) (繼承來自 SwingWorker 上面方法)將會被執行, 並同時終止正在背景執行的工作.

Implementation:
  1. package swing.demo;  
  2.   
  3. import java.awt.BorderLayout;  
  4. import java.awt.Dimension;  
  5. import java.awt.FlowLayout;  
  6. import java.awt.GridLayout;  
  7. import java.awt.event.ActionEvent;  
  8. import java.awt.event.ActionListener;  
  9. import java.util.Random;  
  10.   
  11. import javax.swing.ImageIcon;  
  12. import javax.swing.JButton;  
  13. import javax.swing.JFrame;  
  14. import javax.swing.JLabel;  
  15. import javax.swing.JPanel;  
  16. import javax.swing.JTextField;  
  17. import javax.swing.SwingUtilities;  
  18. import javax.swing.SwingWorker;  
  19. import javax.swing.WindowConstants;  
  20.   
  21.   
  22. public class LuckyNumber extends JFrame implements ActionListener{  
  23.     private static final long serialVersionUID = 4276832367310733568L;  
  24.     private JLabel label;  
  25.     private JButton cancel;  
  26.     private JButton start;  
  27.     private SwingWorker worker;  
  28.     private JTextField textField;  
  29.   
  30.     public LuckyNumber() {  
  31.         JPanel panel = new JPanel();  
  32.         panel.setLayout(new GridLayout(21));  
  33.   
  34.         JPanel buttons = new JPanel(new FlowLayout());  
  35.         start = new JButton("Start");  
  36.         start.addActionListener(this);  
  37.         start.setDefaultCapable(true);  
  38.         buttons.add(start);  
  39.         cancel = new JButton("Cancel");  
  40.         cancel.setEnabled(false);  
  41.         cancel.addActionListener(this);  
  42.         buttons.add(cancel);  
  43.         panel.add(buttons);  
  44.   
  45.         ImageIcon image = new ImageIcon(getClass().getClassLoader().getResource("swing/demo/images/spinner.gif"));        
  46.   
  47.         label = new JLabel(image);  
  48.         JPanel answer = new JPanel(new GridLayout(12));  
  49.         textField = new JTextField("");  
  50.         answer.add(textField);  
  51.         answer.add(label);  
  52.         label.setVisible(false);  
  53.         panel.add(answer);  
  54.   
  55.         setTitle("Lucky number generator");  
  56.         setPreferredSize(new Dimension(300100));  
  57.         getContentPane().setLayout(new BorderLayout());  
  58.         getContentPane().add(panel);  
  59.   
  60.     }  
  61.   
  62.     public static void main(String[] args) {  
  63.         SwingUtilities.invokeLater(new Runnable() {  
  64.             public void run() {  
  65.                 LuckyNumber luckyNumber = new LuckyNumber();  
  66.                 luckyNumber.pack();  
  67.                 luckyNumber.setVisible(true);  
  68.                 luckyNumber.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);  
  69.             }  
  70.         });  
  71.     }  
  72.   
  73.     public void actionPerformed(ActionEvent e) {  
  74.         if (e.getSource() == start) {  
  75.             start.setEnabled(false);  
  76.             textField.setText("");  
  77.             worker = new NumberWorker();  
  78.             worker.execute();  
  79.             label.setVisible(true);  
  80.             cancel.setEnabled(true);  
  81.         } else if (e.getSource() == cancel) {  
  82.             cancel();  
  83.         }  
  84.   
  85.     }  
  86.   
  87.     @Override  
  88.     public void dispose() {  
  89.         cancel();  
  90.         super.dispose();  
  91.     }  
  92.   
  93.     private void cancel() {  
  94.         start.setEnabled(true);  
  95.         label.setVisible(false);  
  96.         cancel.setEnabled(false);  
  97.         if (worker != null) {  
  98.             worker.cancel(true);  
  99.             worker = null;  
  100.         }  
  101.   
  102.     }  
  103.   
  104.     private class NumberWorker extends SwingWorker {  
  105.   
  106.         private Random r = new Random();  
  107.   
  108.         @Override  
  109.         protected String doInBackground() throws Exception {  
  110.             long s = System.currentTimeMillis();  
  111.             while (System.currentTimeMillis() - s < 5000 && !Thread.currentThread().isInterrupted()) {  
  112.                 r.nextInt();  
  113.             }  
  114.             return String.valueOf(r.nextInt(10) + 1);  
  115.         }  
  116.   
  117.         @Override  
  118.         protected void done() {  
  119.             try {  
  120.                 textField.setText(get());  
  121.                 LuckyNumber.this.worker = null;  
  122.                 LuckyNumber.this.cancel();  
  123.             } catch (Exception ignore) {  
  124.             }  
  125.         }  
  126.     }  
  127. }  
Supplement:
The Java Tutorial > Worker Threads and SwingWorker
When a Swing program needs to execute a long-running task, it usually uses one of the worker threads, also known as the background threads. Each task running on a worker thread is represented by an instance of javax.swing.SwingWorker. SwingWorker itself is an abstract class; you must define a subclass in order to create a SwingWorker object; anonymous inner classes are often useful for creating very simple SwingWorker objects.

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!