【问题标题】:Timer application inside SwingWorker Java Swing does not workSwingWorker Java Swing 中的计时器应用程序不起作用
【发布时间】:2015-09-26 23:38:16
【问题描述】:

尝试制作 Java Swing 应用程序的一部分,应该这样做:

  • 单击按钮时,从“分钟”中获取用户值(整数) 一些文本字段;
  • 实例化一个实际上是 SwingWorker 线程的对象,它会在 doInBackground() 完成后启动一个计时器,将用户“分钟”计数回零,然后在 done() 中执行一些操作(启动另一个 JFrame);

我在代码中的某些点上打印,似乎代码从 textField 获取输入分钟,将其传递给 Countdown 类中的构造函数,但随后简单地执行 done(),而不先运行 doInBackground()。

如果有人暗示为什么会发生这种情况,我会很感激,我已经尝试了所有的想法,但没有任何效果。

这是第一部分,来自 Button 的代码:

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {

userCountTime = Integer.parseInt(jTextField2.getText());
        userCountTime = userCountTime * 60;
        System.out.println("Preuzeto iz dugmeta " + userCountTime);

        if (jRadioButton2.isSelected()){
            Countdown countDown= new Countdown (userCountTime);
}

这里是 Countdown 类:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.SwingWorker;
import javax.swing.Timer;

/**
 *
 * @author Glupko
 */
public class Countdown extends SwingWorker{
   public Timer timer;
   static int userCountTime;
   static ActionListener timerListener;

   //Constructor
        public Countdown (int userCountTime){
        Countdown.userCountTime = userCountTime;
        System.out.println("In constructor: " + Countdown.userCountTime);
        this.execute();
        }

    @Override
    protected Object doInBackground() throws Exception {
        //defining listener
        timerListener = new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent actionEvent) {
                   System.out.println("In action performed value is:  " + userCountTime); 

                   //for each tick we subtract 1, every second 
                   while (userCountTime >= 0){
                        userCountTime--;
                    System.out.println("In actionPerformed there is number of seconds:  " + userCountTime);}
                timer = new Timer(1000, timerListener);
                //start timer
                timer.start();
                }};}
     @Override
            protected void done(){
                System.out.println("From done: timer elapsed");
                ChangingWindow window = new ChangingWindow();
                }
        }

非常感谢!

【问题讨论】:

  • 1) 您不应该在 SwingWorker 的 doInBackground 方法中启动 Swing Timer。这违背了所有目的,因为 Swing 计时器应该在 Swing 事件线程或 EDT 上运行。 2) 你的 SwingWorker 的 done 方法将被立即调用,因为 timer.start() 是非阻塞的
  • 感谢 Hovercraft Full Of Eels,我已经让它工作了 :) 只是出于好奇 - 在我的情况下,当计时器运行时,所有按钮都被阻止并且应用程序只是在等待计时器完成,这很好。如果应用程序更大,这会阻塞整个 EDT,是吗?在这种情况下,我将如何为非常具体的任务实现计时器?再次感谢您的帮助!
  • 如果操作正确,计时器不应阻塞。您是否还有其他可能会阻塞我们不知道的 EDT 的长期运行代码?
  • 不,计时器是唯一的。这是一个非常小的应用程序,仅用于练习。你刚刚给了我一个答案“..如果做得正确,它不应该阻塞。”再次感谢!

标签: java swing timer swingworker


【解决方案1】:
  1. 您不应该在 SwingWorker 的 doInBackground 方法中启动 Swing 计时器。这违背了所有目的,因为 Swing 计时器应该在 Swing 事件线程或 EDT 上运行。
  2. 您的 SwingWorker 的 done 方法将立即被调用,因为 timer.start() 是非阻塞的。

改为摆脱 SwingWorker 并简单地使用 Timer。

如需更完整的代码帮助,请考虑创建并发布您的 minimal code example program 以供我们审核、测试并可能修复。

例如,。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.*;

public class CountDownTest extends JPanel {
    private static final Integer[] SECONDS = {1, 2, 3, 4, 5, 6, 7, 8, 9};

    private JSpinner secondsSpinner = new JSpinner(new SpinnerListModel(Arrays.asList(SECONDS)));

    public CountDownTest() {
        add(secondsSpinner);
        add(new JButton(new StartCountDownAction(this, "Start Count Down")));
    }

    public int getSecondsSpinnerValue() {
        return (Integer) secondsSpinner.getValue();
    }

    private static void createAndShowGui() {
        CountDownTest mainPanel = new CountDownTest();

        JFrame frame = new JFrame("CountDownTest");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}

class StartCountDownAction extends AbstractAction {
    private CountDownTest countDownTest;
    private Timer timer;

    public StartCountDownAction(CountDownTest countDownTest, String name) {
        super(name);
        this.countDownTest = countDownTest;
        int mnemonic = (int) name.charAt(0);
        putValue(MNEMONIC_KEY, mnemonic);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (timer != null && timer.isRunning()) {
            // don't start a new Timer when one is running
            return; 
        }
        int seconds = countDownTest.getSecondsSpinnerValue();
        timer = new Timer(seconds * 1000, new TimerListener(countDownTest));
        timer.setRepeats(false);
        timer.start();
    }
}

class TimerListener implements ActionListener {
    private CountDownTest countDownTest;

    public TimerListener(CountDownTest countDownTest) {
        this.countDownTest = countDownTest;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        JOptionPane.showMessageDialog(countDownTest, "Timer Done!");
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    相关资源
    最近更新 更多