简体   繁体   中英

How do I wait for a timer to stop before executing code?

I have a Timer that is used in a class that extends JPanel for an animation, and an ActionListener listens to it and makes actionPerformed run, which does repainting and stops the timer when needed. But the method that starts the timer, animatePanel, continues executing as the timer is running, which is what I do NOT want. I want it to wait until the timer has stopped to return.

The Timer is initialized in the class's constructor like this:

timer = new Timer(5, taskPerformer);

And this is what it does. I have something call animatePanel():

    private ActionListener taskPerformer = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        ...
        if (some conditions){
            ...
            timer.stop();
            ...
            return;
        }

        ...
    }
};

private void animatePanel() {
    ...
    timer.start();
    System.out.println("Timer stopped."); //always executes before the timer has stopped :(
    //then returns and lets the rest of my program run while the timer is still going, which is BAD
}

The timer works fine except that in some cases, animatePanel() will return too soon and let the rest of my program run, causing problems.

You CAN NOT do this from within the context of the Event Dispatching Thread, doing so will make you application hang!

The timer must be started in a separate Thread . This then lets you take advantage of the thread monitoring API.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class WaitForTimer {

    public static void main(String[] args) {
        new WaitForTimer();
    }

    public WaitForTimer() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        protected static final Object WAIT_FOR = new Object();
        private Timer timer;
        private int tickCount = 0;
        private JLabel ticks;
        private JButton start;

        public TestPane() {
            timer = new Timer(250, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    tickCount++;
                    if (tickCount > 10) {
                        tickCount = 0;
                        timer.stop();
                        synchronized (WAIT_FOR) {
                            WAIT_FOR.notifyAll();
                        }
                        start.setEnabled(true);
                    }
                    ticks.setText(String.valueOf(tickCount));
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);

            ticks = new JLabel("...");
            start = new JButton("Start");

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(ticks, gbc);
            add(start, gbc);

            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    start.setEnabled(false);
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println("Starting timer...");
                            timer.start();
                            synchronized (WAIT_FOR) {
                                try {
                                    WAIT_FOR.wait();
                                } catch (InterruptedException ex) {
                                }
                            }
                            System.out.println("Timer finished...");
                        }
                    }).start();
                }
            });

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    }
}

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