1. EDT (Event Dispatch Thread)
Question: Why are GUIs Single-threaded?
1) 不要再EDT执行时间较长的任务,否则GUI无法及时响应。
2) SwingUtilities.invokeLater() 可以将一个Runnable任务调度到事件线程中执行(可以在任意线程中调用)
2. 短时间的GUI任务
在EDT中处理
3. 长时间的GUI任务
使用SwingWorker,支持取消、进度标识和完成标识(可以考虑用于改正以前的假进度条了)。
下面是一个demo,from http://www.java2s.com/Code/Java/JDK-6/SwingWorkerfromJDK6SE.htm
import java.awt.LayoutManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingWorker; public class SwingWorkerDemo { public static void main(String[] args) { JTextArea textArea = new JTextArea(10, 20); final JProgressBar progressBar = new JProgressBar(0, 10); final CounterTask task = new CounterTask(); task.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { progressBar.setValue((Integer) evt.getNewValue()); } } }); JButton startButton = new JButton("Start"); startButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { task.execute(); } }); JButton cancelButton = new JButton("Cancel"); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { task.cancel(true); } }); JPanel buttonPanel = new JPanel(); buttonPanel.add(startButton); buttonPanel.add(cancelButton); JPanel cp = new JPanel(); LayoutManager layout = new BoxLayout(cp, BoxLayout.Y_AXIS); cp.setLayout(layout); cp.add(buttonPanel); cp.add(new JScrollPane(textArea)); cp.add(progressBar); JFrame frame = new JFrame("SwingWorker Demo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(cp); frame.pack(); frame.setVisible(true); } } class CounterTask extends SwingWorker<Integer, Integer> { private static final int DELAY = 1000; public CounterTask() { } @Override protected Integer doInBackground() throws Exception { int i = 0; int count = 10; while (!isCancelled() && i < count) { i++; publish(new Integer[] { i }); setProgress(count * i / count); Thread.sleep(DELAY); } return count; } protected void process(List<Integer> chunks) { System.out.println("process : " + Thread.currentThread().getName()); for (int i : chunks) System.out.println(i); } @Override protected void done() { System.out.println("done : " + Thread.currentThread().getName()); if (isCancelled()) System.out.println("Cancelled !"); else System.out.println("Done !"); } }
process : AWT-EventQueue-0 1 process : AWT-EventQueue-0 2 process : AWT-EventQueue-0 3 process : AWT-EventQueue-0 4 process : AWT-EventQueue-0 5 process : AWT-EventQueue-0 6 process : AWT-EventQueue-0 7 process : AWT-EventQueue-0 8 process : AWT-EventQueue-0 9 process : AWT-EventQueue-0 10 done : AWT-EventQueue-0 Done !
可以看出,progress(在事件指派线程 上异步地从 publish
方法接收数据块)方法果然是被EDT线程调度的。