CannotCode
CannotCode

Reputation: 53

How to call a Swing Timer from Inside a JButton

I'm trying to start a Timer after a button is pressed.

The following code without a button works

    Timer timer = new Timer(1000, new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("test");
        }
    });
    timer.start();
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

However when I put it inside a button

    startButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            Timer timer = new Timer(1000, new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.out.println("test");
                }
            });
            timer.start();
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

It does not print anything when the button is pressed.

I thought this occurred because the main thread ends, so I tried adding a while (true) at the end, but it did not change anything.

Thanks

Upvotes: 2

Views: 289

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347194

Get rid of Thread.sleep(10000);, it's cause the Event Dispatching Thread to sleep for 10 seconds, which is stopping it from process the the Event Queue, which where the Timer will post it's "action" events to run

Take a look at The Event Dispatch Thread for more details

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) throws IOException {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            JButton btn = new JButton("Start");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    Timer timer = new Timer(1000, new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent arg0) {
                            System.out.println("...");
                        }
                    });
                    timer.start();
                }
            });
            add(btn);
        }

    }


}

but how would I stop it after a certain time now?

That's a more difficult answer. First, you would need to make it an instance field so you can reference it.

Second, you could either use a second Timer, set to the specified timeout (and set not to repeat) and when it fires, stop the first Timer or, use something like Instant to calculate the difference between when the timer was started and now, for example and example (at the lest the second half)

Upvotes: 1

Related Questions