SwingWorker,取消按钮不起作用

时间:2014-01-20 14:17:03

标签: java multithreading swing swingworker

我有一个窗口,带有开始和停止按钮。开始按钮启动算法,停止按钮应该停止它。我使用SwingWorker在后​​台运行算法,通常调用worker.cancel(true)应该停止算法运行。我还有一个可视化状态的标签,例如如果我按下“停止”,则Labeltext会变为“已停止”,因此问题不在按钮的actionLister上。

我的代码如下所示:

public class MainWindow extends JFrame implements ActionListener, WindowListener
{
 // Some code, like generating JFrame, JButtons and other stuff not affencting the task.

 Worker worker = new Worker();

    public void actionPerformed(ActionEvent e)
    {       
    boolean isStarted = false;



    // Start Button
    if (e.getSource() == this.buttonStart)
    {
        if(!isStarted)
        {
        System.out.println("start");
        labelSuccess.setText("Mapping started!");
        this.setEnabled(true);
        worker.execute();
        isStarted = false;
        }
    }
    // Stop Button
    if (e.getSource() == this.buttonStop)
        {
        labelSuccess.setText("Mapping stopped!");
        worker.cancel(true);
        }
  }

class Worker extends SwingWorker<Void, Void> {

    @Override
    protected Void doInBackground() throws Exception {

    if(!isCancelled())
    {
        mapp();
        Thread.sleep(60);
    if (isCancelled()) {
     System.out.println("SwingWorker - isCancelled");
    }
    }
        return null;
    }

}

在此点,按停止按钮只会更改Label-Text,但后台的算法仍在运行。现在这困扰了我很长一段时间,我无法顺利进行。

非常感谢您的帮助,非常感谢。

edit1:我现在在actionPerformed之外生成一个新的worker实例,所以现在每次鼠标点击都没有生成新的Worker。

2 个答案:

答案 0 :(得分:2)

如果您在while课程的if方法上使用doInBackground()而不是Worker,则可以解决您的问题。您必须退出while循环mapp(),因为您只想调用它一次。你应该这样做:

class Worker extends SwingWorker<Void, Void> {

    @Override
    protected Void doInBackground() throws Exception {

    mapp();    
    while(!isCancelled()){
        Thread.sleep(60);
    }
     System.out.println("SwingWorker - isCancelled");    
        return null;       
}

link可能有助于了解如何使用SwingWorker

修改

正如您在thisthis等其他问题上看到的那样,使用SwingWorker管理cancel方法存在一些问题,因为此方法尝试取消执行此任务。如果任务已经完成,已被取消,或因某些其他原因无法取消 ,如Oracle解释,以及那些“其他”,此尝试将失败原因“在我发布的链接上进行了讨论。

您可以直接使用Threads解决问题。你的代码是这样的:

    public class MainWindow extends JFrame implements ActionListener, WindowListener
    {
     // Some code, like generating JFrame, JButtons and other stuff not affencting the task.

        final Thread th1 = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        mapp();                 

                    }
                }); 
        public void actionPerformed(ActionEvent e)
        {       
        boolean isStarted = false;

    // Start Button
    if (e.getSource() == this.buttonStart)
    {
        if(!isStarted)
        {
        System.out.println("start");
        labelSuccess.setText("Mapping started!");
        this.setEnabled(true);
        th1.start();
        isStarted = false;
        }
    }
    // Stop Button
    if (e.getSource() == this.buttonStop)
        {
        labelSuccess.setText("Mapping stopped!");
        th1.stop();
        }
  }

此解决方案使用的方法stop()已弃用,但可以使用。我尝试过使用interrupt(),但我不知道为什么线程会运行直到完成mapp()的执行。显然,使用stop()并不是最好的方法,但它可以在mapp()执行完成之前停止执行。

我建议您详细了解SwingWorkerThreadTask,以找到问题的最佳解决方案。

答案 1 :(得分:1)

你的问题是worker中没有循环:如果你想使用标志取消进程,那个进程应该不时地检查标志,所以如果你的方法Worker.mapp()必须被停止,检查那里的标志,不是在调用它之前和之后。