cangrejo
cangrejo

Reputation: 2202

Java Swing Timer only runs once

Can anyone tell me why does this timer run only once?

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TimerTest implements ActionListener{

    private Robot r;
    private Timer t;
    private int i;

    public TimerTest(){     
        i = 0;  
        try {
            r = new Robot();
        } catch (AWTException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
        t = new Timer(1000, this);  
        t.setRepeats(true);
        t.start();  
    }

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

    @Override
    public void actionPerformed(ActionEvent arg0) {
        i++;
        System.out.println("Action..." + i);        
    }

The funny thing is that, if I decrease the delay in the Timer to just 100, it works as expected. And what's even funnier is that if I delete the code in which I initialize the Robot, it doesn't work at all, the program terminates as soon as I run it.

I've tried this on Windows 7 and on Ubuntu (although on Ubuntu I couldn't use the Robot at all, since I get an exception. Something related to rights, maybe).

Upvotes: 2

Views: 2333

Answers (2)

Halfwarr
Halfwarr

Reputation: 8103

Your main is processed so the program stops. You can test it by using this code, adding it to TimerTest()

JFrame testFrame = new JFrame();
testFrame.setVisible(true);
testFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

That JFrame keeps your main not from finshing, when you close the Frame the TimerTest ends. Which concludes your main which causes the main to finsh. Ending the program and stoping your swing timer.

Upvotes: 5

Andrew Thompson
Andrew Thompson

Reputation: 168815

See "main exits before javax.swing.Timer's start() can start" at the bug database.


Evaluation

Described behavior - when application exits before Swing timer is started - is correct. Here is what's going then:

  1. Swing timer is created.
  2. Separate thread for swing timer is started. It will notify attached actionListeners when the timeout is passed by posting an instance of InvocationEvent to EDT.
  3. Main thread exits.
  4. At this moment there is no non-daemon threads running in JVM. Application is terminated.

..the evaluator goes on to add..

..This looks like a RFE rather than a defect.


One surefire way to make it behave is to create a GUI element and display it. Which is why I asked earlier..

..why exactly are you creating the timer without any GUI elements? Is this for repeated screen-shots?

To handle that situation, I would typically create and show a frame to allow the user to configure the rate and area for screenshots, then minimize the frame and begin processing when the user clicks:

Screen Capture!

Upvotes: 2

Related Questions