【问题标题】:How to cancel done() in a SwingWorker thread?如何在 SwingWorker 线程中取消 done()?
【发布时间】:2016-05-26 08:32:43
【问题描述】:

我正在制作一个程序,它应该能够通过单击按钮来停止整个过程。

我已经使用sw.cancel(true); 这样做了,但是SwingWorker 方法protected void done() 仍在运行。

如何一键取消整个操作?不只是doInBackground() 方法?

下面是完整的相关代码供感兴趣的人参考:

sw = new SwingWorker() {
    protected Object doInBackground() throws Exception {
        //Pravljenje timera
        t = new Timer(0, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            }
        });

        //Provera stanja checkboxova
        if(jCheckBox2.isSelected()) {
            try {
                int delay =(int) jSpinner2.getValue();
                jCheckBox1.setSelected(false);
                Thread.sleep(delay*60000);
            } catch (InterruptedException ex) {
                Logger.getLogger(App_Gui.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        if(jCheckBox1.isSelected()) {
            jCheckBox2.setSelected(false);   

            Date delay2 = (Date) jSpinner1.getValue();
            userCal = Calendar.getInstance();
            System.out.println("delay2: " + delay2);
            userCal.setTime(delay2);
            System.out.println("userCal:" + userCal);
            Calendar sysCal = Calendar.getInstance();
            System.out.println("sysCal: " + sysCal);
            timerAtDate = 
                (((int) userCal.get(Calendar.HOUR_OF_DAY) - (int) sysCal.get(Calendar.HOUR_OF_DAY)) * 60 * 60 * 1000 +
                ((int) userCal.get(Calendar.MINUTE) - (int) sysCal.get(Calendar.MINUTE)) * 60 * 1000 +
                ((int) userCal.get(Calendar.SECOND) - (int) sysCal.get(Calendar.SECOND)) * 1000);
            Thread.sleep(timerAtDate);
        }

        return null; 
    }

    @Override
    protected void done() {
        System.out.println("Done!");

        t.start();
        t.setRepeats(false);
        JDialog dialog = new JDialog();
        dialog.setLocation(700, 300);
        dialog.setSize(600, 400);
        dialog.setVisible(true);
        try {
            Thread.sleep(jSlider1.getValue());
        } catch (InterruptedException ex) {
            Logger.getLogger(App_Gui.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("Zapravo gotov");
        dialog.getContentPane().setBackground(jLabel2.getBackground());
        dialog.setModal(true);
        Assignment_Tajmer_Aplikacija.f.setVisible(false); 
    }
};

sw.execute();

private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {
    // TODO add your handling cosadde here:
    jSlider1.addChangeListener(new ChangeListener() {
        public void stateChanged(ChangeEvent e) {
            JSlider source = (JSlider) e.getSource();
            //System.out.println(source.getValue());
        }
    });
}                                     

private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
    // TODO add your handling code here:
    JColorChooser jcc = new JColorChooser();
    Color c = jcc.showDialog(null, "Choose background color", Color.yellow);
    jLabel2.setForeground(c);
    jLabel2.setBackground(c);
    jLabel2.setText("Color: " + c.getRGB() + "(RGB)");
}                                        

private void jCheckBox2ActionPerformed(java.awt.event.ActionEvent evt) {
    // TODO add your handling code here:
    jCheckBox1.setSelected(false);
}                                          

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
    // TODO add your handling code here:
    sw.cancel(true);
}                                        

private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {
    // TODO add your handling code here:
    jCheckBox2.setSelected(false);
}                                          

【问题讨论】:

  • SwingWorker 通常用于在后台进行耗时的处理,因此它不会冻结 UI。它还允许您向 UI 发送更新,例如更新进度条。在你的情况下,我看不到这样的东西,这让我想知道你为什么要使用SwingWorker
  • 代码还有很多,我用的是SwingWorker,因为定时器可以设置为未来10年,我从来没有设置最大值,我不希望程序冻结10年 :P 并且为了更容易按下取消计时器并允许用户再次访问其他按钮的“停止”按钮(因为当他们点击开始时,除了“停止”之外的所有其他按钮都无法点击)~
  • 您对doInBackground() 的实现未正确同步; event dispatch thread 上操作 Swing GUI 对象。请更新您的问题以解释actual problem
  • 这可能是一个非常耗时的过程,可能需要长达 10 年的等待时间,因此我使用了 SwingWorker,这样程序就不会死机。

标签: java multithreading swing action swingworker


【解决方案1】:

使用done()开头的isCancelled()方法看是否应该做这些操作。

【讨论】:

  • 等等,所以在 done() 方法的开头我输入了 sw.isCancelled(),然后呢?它应该返回 SwingWorker 的状态,我怎样才能使用返回的值来停止使用代码进行的 done() 方法?提前致谢!
  • 好吧,你可能猜到isCancelled() 返回一个布尔值。与if 声明配合使用会非常好。
  • 所以,如果它返回“true”,我继续写: if (sw.isCancelled == true) { //停止方法 } 但是我应该写什么而不是评论来实际停止方法?
  • 您决定跳过基础知识,直接进入 Swing,不是吗?我建议你在继续编程之前学习如何使用if 子句。
  • 不,不是真的......我猜我犯了一个非常愚蠢和基本的错误,但我是 Swing 的新手,这是我迄今为止学习中最难的部分 :(
【解决方案2】:

您无法取消它,但您可以将其短路,以便提前完成。在线程之间使用一些共享状态标志来发出信号。

【讨论】:

  • 所以我做了一个在doInBackground()中调用的方法?那个方法会停止 done() 方法吗?但是我应该在方法中写什么?那是那里的问题:D
猜你喜欢
  • 1970-01-01
  • 2011-12-26
  • 1970-01-01
  • 2015-02-07
  • 2011-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-01
相关资源
最近更新 更多