I am trying to print a statement repeatedly using Swing Timer but the statement doesn't gets printed !
What's the mistake I am making ?
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class SwingTimer implements ActionListener {
Timer timer;
public static void main(String[] args) {
SwingTimer obj = new SwingTimer();
obj.create();
}
public void create() {
timer = new Timer(1000, this);
timer.setInitialDelay(0);
timer.start();
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Hello using Timer");
}
}
The javax.swing.Timer probably starts as a daemon thread: it doesn't keep the jvm alive, your main ends, the jvm exits. It post the timer events to the GUI event queue which starts when the first dialog or frame is made visible.
You have to create a JFrame, and make it visible or use the java.util.Timer if you don't need windowing system at all.
The following code shows how to use java.util.Timer:
import java.util.Timer;
import java.util.TimerTask;
public class TimerDemo extends TimerTask {
private long time = System.currentTimeMillis();
#Override public void run() {
long elapsed = System.currentTimeMillis() - time;
System.err.println( elapsed );
time = System.currentTimeMillis();
}
public static void main( String[] args ) throws Exception {
Timer t = new Timer( "My 100 ms Timer", true );
t.schedule( new TimerDemo(), 0, 100 );
Thread.sleep( 1000 ); // wait 1 seconde before terminating
}
}
javax.swing.Timer should only be used when using Swing applications. Currently your main Thread is exiting as the Timer uses a daemon Thread. As a workaround you could do:
public static void main(String[] args) {
SwingTimer obj = new SwingTimer();
obj.create();
JOptionPane.showMessageDialog(null, "Timer Running - Click OK to end");
}
An alternative for non-UI applications is to use ScheduledExecutorService
Related
Here is my main class
import javax.swing.Timer;
public class Test {
public static int k=9;
public static void main(String[] args) {
Timer t = new Timer(100, new Loop());
t.start();
}
}
And my class Loop which implements ActionListener
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Loop implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if(Test.k==9){
System.out.println("Its's Working");
}
}
}
I don't know why? When I've fully what it need but it doesn't print "Its's Working" in the console
And one more question is that "Is this Timer class similar to Thread in java ?"
Thanks for your answer!
Your program exits immediately after stating the timer, giving it no chance to fire.
The AWT Event Dispatch Thread (EDT) will need to have started for some reason in order for the timer to stay alive.
Swing is supposed to be use from this thread. If you do so, it should work.
java.awt.EventQueue.invokeLater(() -> {
Timer t = new Timer(100, new Loop());
t.start();
});
To avoid indenting a lot of code , and to have a short main, I tend to create a method call go and use a method reference.
java.awt.EventQueue.invokeLater(Test::go);
private static void go() {
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class TimeController {
public static void main(String arg[]){
TimeController m = new TimeController();
System.out.println("starting");
m.start();
}
Timer timer = new Timer (1000, new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("Running");
}
});
public void start(){
timer.start();
}
}
I think there is no fault at all.
The Timer starts its task in the background
Your application terminates before the first execution of the Timers method takes place.
For testing you could add
try {
Thread.sleep(5000);
} catch(Exception e){
// Add exception handling
}
right after `m.start();
For some reason the Timer needs to fire at least once to prevent the program from termination. After it fires once, it does hold the program running, even after the main method terminates.
Probably the bug got unnoticed as this is a rather unusual work flow. Delay the termination of the main thread as proposed by #StefanFreitag.
Bellow is the code for the simplest GUI countdown. Can the same be done in a shorter and more elegant way with the usage of the Swing timer?
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class CountdownNew {
static JLabel label;
// Method which defines the appearance of the window.
public static void showGUI() {
JFrame frame = new JFrame("Simple Countdown");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label = new JLabel("Some Text");
frame.add(label);
frame.pack();
frame.setVisible(true);
}
// Define a new thread in which the countdown is counting down.
public static Thread counter = new Thread() {
public void run() {
for (int i=10; i>0; i=i-1) {
updateGUI(i,label);
try {Thread.sleep(1000);} catch(InterruptedException e) {};
}
}
};
// A method which updates GUI (sets a new value of JLabel).
private static void updateGUI(final int i, final JLabel label) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
label.setText("You have " + i + " seconds.");
}
}
);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
showGUI();
counter.start();
}
});
}
}
Yes you SHOULD use a Swing Timer. You SHOULD NOT, use a util Timer and TimerTask.
When a Swing Timer fires the code is executed on the EDT which means you just need to invoke the label.setText() method.
When using the uitl Timer and TimerTask, the code DOES NOT execute on the EDT, which means you need to wrap your code in a SwingUtilities.invokeLater to make sure the code executes on the EDT.
And that is way using a Swing Timer is shorter and more elegant than your current approach, it simplifies the coding because to code is executed on the EDT.
You could make it a little more elegant by using Timer with an appropriate TimerTask.
Yes, use a timer. updateGUI would be the code for the timer task, but it will need some changes as you won't be able to pass in i for each call since you just get a run() method.
I have simple Timer console application. Why this application not stops after run procedure was executed and still waiting for something?
package timer_old;
import java.util.Timer;
import java.util.TimerTask;
public final class FetchMail extends TimerTask {
public static void main (String[] args)
{
System.out.println("starting");
TimerTask fetchMail = new FetchMail();
Timer timer = new Timer();
timer.schedule(fetchMail, 500);
//timer.cancel();
System.out.println("exiting");
}
public void run()
{
System.out.println("Fetching mail...");
}
}
Output:
starting
exiting
Fetching mail...
From the docs:
By default, the task execution thread does not run as a daemon thread, so it is capable of keeping an application from terminating. If a caller wants to terminate a timer's task execution thread rapidly, the caller should invoke the timer's cancel method.
you need to call timer.cancel() when you want the timer to terminate as soon as the run is executed.
public final class FetchMail extends TimerTask {
static Timer timer=null;
public static void main (String[] args)
{
System.out.println("starting");
TimerTask fetchMail = new FetchMail();
timer= new Timer();
timer.schedule(fetchMail, 3000);
//timer.cancel();
System.out.println("exiting");
}
public void run()
{
System.out.println("Fetching mail...");
timer.cancel();
}
}
I want to run a timer which says time is expired after 30 seconds,how can do so?
Some task to be run only for some seconds then showing expired, how can i do so?
I'd recommend using ScheduledExecutorService from the java.util.concurrent package, which has a richer API than other Timer implementations within the JDK.
// Create timer service with a single thread.
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
// Schedule a one-off task to run in 10 seconds time.
// It is also possible to schedule a repeating task.
timer.schedule(new Callable<Void>() {
public Void call() {
System.err.println("Expired!");
// Return a value here. If we know we don't require a return value
// we could submit a Runnable instead of a Callable to the service.
return null;
}
}, 10L, TimeUnit.SECONDS);
The actionPerformed method is called after 30 sec
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
public class TimerExample {
public static void main(String args[]) {
new JFrame().setVisible( true );
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
System.out.println( "expired" );
}
};
Timer timer = new Timer( 30000, actionListener );
timer.start();
}
}
Use Timer.