简体   繁体   中英

Timer application inside SwingWorker Java Swing does not work

trying to make one part of Java Swing app, which should do:

  • when a button is clicked, takes user value (integer) of "minutes" from some text field;
  • instantiates and object which is actually SwingWorker thread, which will start a timer a count back to zero user "minutes" and then perform some action (initiate another JFrame) in done(), after doInBackground() finishes;

I put prints on some points in the code and it seems that the code takes input minutes from textField, passes it to the Constructor in Countdown class, but then simply executes done(), without running doInBackground() first.

If anybody has some hint why is this happening I would be thankfull, I have tried all my ideas and nothing works.

Here is the first part, code from the 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);
}

Here is the class 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();
                }
        }

Many thanks in advance!

  1. You shouldn't be starting a Swing Timer from within a SwingWorker's doInBackground method. That defeats all purposes, since a Swing Timer should be run on the Swing event thread or EDT.
  2. Your SwingWorker's done method will be called immediately since the timer.start() is non-blocking.

Instead get rid of the SwingWorker and simply use the Timer on its own.

For more complete help with code, please consider creating and posting your minimal code example program for us to review, test, and possibly fix.

eg,.

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!");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM