【发布时间】:2014-09-17 11:44:12
【问题描述】:
我已经和SwingWorkers 合作了一段时间,结果出现了一种奇怪的行为,至少对我来说是这样。我清楚地明白,由于性能原因,对publish() 方法的多次调用在一次调用中合并。这对我来说非常有意义,我怀疑 SwingWorker 会保留某种队列来处理所有调用。
根据tutorial和API,当SwingWorker结束执行时,要么doInBackground()正常结束要么从外部取消工作线程,然后调用done()方法。到目前为止一切顺利。
但我有一个示例(类似于教程中所示),其中有process() 方法调用完成 done() 方法被执行。由于这两种方法都在Event Dispatch Thread 中执行,我希望done() 在所有process() 调用完成后执行。换句话说:
预期:
Writing...
Writing...
Stopped!
结果:
Writing...
Stopped!
Writing...
示例代码
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class Demo {
private SwingWorker<Void, String> worker;
private JTextArea textArea;
private Action startAction, stopAction;
private void createAndShowGui() {
startAction = new AbstractAction("Start writing") {
@Override
public void actionPerformed(ActionEvent e) {
Demo.this.startWriting();
this.setEnabled(false);
stopAction.setEnabled(true);
}
};
stopAction = new AbstractAction("Stop writing") {
@Override
public void actionPerformed(ActionEvent e) {
Demo.this.stopWriting();
this.setEnabled(false);
startAction.setEnabled(true);
}
};
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(new JButton(startAction));
buttonsPanel.add(new JButton(stopAction));
textArea = new JTextArea(30, 50);
JScrollPane scrollPane = new JScrollPane(textArea);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(scrollPane);
frame.add(buttonsPanel, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void startWriting() {
stopWriting();
worker = new SwingWorker<Void, String>() {
@Override
protected Void doInBackground() throws Exception {
while(!isCancelled()) {
publish("Writing...\n");
}
return null;
}
@Override
protected void process(List<String> chunks) {
String string = chunks.get(chunks.size() - 1);
textArea.append(string);
}
@Override
protected void done() {
textArea.append("Stopped!\n");
}
};
worker.execute();
}
private void stopWriting() {
if(worker != null && !worker.isCancelled()) {
worker.cancel(true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Demo().createAndShowGui();
}
});
}
}
【问题讨论】:
-
根据经验,当worker的后台延迟超过
DELAY时是看不到效果的。 -
最后,一个好的问题出现在我的首页。
标签: java swing swingworker