我正在尝试通过单击 JFrame 表单上的按钮来取消某个功能。
这是我的工作函数:
private void start(final Callable<Void> func) {
worker = new SwingWorker<Boolean, Integer>() {
@Override
protected Boolean doInBackground() throws Exception {
publish(2);
func.call();
return true;
}
@Override
protected void done() {
boolean status;
try {
status = get();
dialog.dispose();
} catch (InterruptedException | ExecutionException e) {
progressBar.setString("ERROR");
Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, e);
}
}
@Override
protected void process(List<Integer> chunks) {
progressBar.setStringPainted(true);
progressBar.setIndeterminate(true);
}
};
这就是我试图取消 SwingWorker 对象的方法:
dialog.addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
worker.cancel(true);
}
});
但是当我单击关闭按钮时,它给了我异常,并且在 doinBackground()
方法内没有取消 func
。如何停止 func
方法?
最佳答案
在一次关于Callable的可怜的误会之后和 CallableStatement接口(interface)(很抱歉,我必须暂时离开 JDBC :P)我所说的观点仍然有效(幸运的是)。您可以使用SwingWorker#isCancelled() done() 内的方法实现如下:
@Override
protected void done() {
if(isCancelled()) {
try {
func.cancel(); // you need to provide this method
dialog.dispose();
} catch(InterruptedException ex) {
progressBar.setString("ERROR");
Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
当然,您需要为可调用实现提供一个 cancel()
方法,该方法可能很简单也可能很困难,具体取决于 call()
方法实际执行的操作。例如:
abstract class AbstractCancellableTask<T> implements Callable<T> {
public abstract void cancel() throws InterruptedException;
}
示例
我已经使用 Callable
更新了之前的示例。请注意,当调用 worker.cancel(true)
方法时,任务将被取消。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class Demo {
private void createAndShowGUI() {
final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
private AbstractCancellableTask<Void> myCallable;
@Override
protected Void doInBackground() throws Exception {
myCallable = new AbstractCancellableTask<Void>() {
private volatile boolean flag = true;
@Override
public void cancel() throws InterruptedException {
flag = false;
}
@Override
public Void call() throws Exception {
while(flag) {
System.out.println("Running heavy task...");
}
System.out.println("Stopped!");
return null;
}
};
myCallable.call();
return null;
}
@Override
protected void done() {
if(isCancelled()) {
try {
myCallable.cancel();
} catch (InterruptedException ex) {
Logger.getLogger(Demo.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
JToggleButton button = new JToggleButton("Start...", false);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JToggleButton toggleButton = (JToggleButton)e.getSource();
if(toggleButton.isSelected()) {
worker.execute();
toggleButton.setText("Stop it!");
} else {
worker.cancel(true);
toggleButton.setEnabled(false);
}
}
});
JPanel content = new JPanel();
content.add(button);
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Demo().createAndShowGUI();
}
});
}
abstract class AbstractCancellableTask<T> implements Callable<T> {
public abstract void cancel() throws InterruptedException;
}
}
关于java - SwingWorker 中的取消异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22529451/