I am using Swing Timer to delay my task for a specific period of time. This time interval is decided by the user.
In my GUI, I have a SpinnerDateModel to accept the time at which the task has to be performed.
SpinnerDateModel date = new SpinnerDateModel();
JSpinner spinner = new JSpinner(date);
frame.getContentPane().add(spinner);
Date futureDate = date.getDate();
Now, Timer has arguments Timer(int delay, ActionListener task)
ActionListener task = new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
//send function
}
};
Timer timer = new Timer(delay, task);
timer.setRepeats(false);
timer.start();
How do I set this delay to the time specified by the user?
With some checking to prevent a negative delay, something like:
delay=Math.max(0,futureDate.getTime()-System.currentTimeMillis());
delay=Math.min(delay,Integer.MAX_VALUE);
// or:
// if(delay>Integer.MAX_VALUE) { throw new exception-of-some-sort }
Timer timer=new Timer((int)delay,task);
should do the trick.
This will calculate the delay based on the number of milliseconds from now until the (presumed future) date selected by the user.
Related
Trying to make a timer that displays the time that has elapsed since a button has been pressed. I am using a Date instance and am trying to have it be initalized to 00:00:00 and have it increase by seconds, mins, then hours. it works as just a clock of the current time if I do not enter any values into Date currentTime = new date()
Here is my code, I have tried setting the Date to all 0 values, and it displays as all zeros, but when my button is pressed, it no longer functions as a timer. What is the problem?
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Date currentTime = new Date(0,0,0,0,0,0);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
laserOnTimeTF.setText(sdf.format(currentTime));
}
});
laserOnOff.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!laserSetting) {
timer.start();
laserSetting = true;
laserOnOff.setText("Laser On");
} else {
timer.stop();
laserSetting = false;
laserOnOff.setText("Laser Off");
}
}
});
That Date constructor is deprecated, like all Date constructors other than the one that takes a milliseconds argument. APIs are deprecated for a reason, usually because they don’t work as intended. To be notified when you use deprecated APIs, turn on all compiler warnings in your IDE, and pay attention to those warnings.
Date is not a good fit for storing elapsed time, since it represents an absolute point in time. The class which is designed to represent a time difference is java.time.Duration.
You can calculate a Duration from two time values. The simplest time value is probably Instant, so you will want a private field of type Instant in the class which creates the Timer and adds a listener to the button, to keep track of when the button was pressed:
private Instant timeOfLastButtonPress;
Then you can initialize it each time the button is actually pressed:
laserOnOff.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!laserSetting) {
timeOfLastButtonPress = Instant.now();
timer.start();
laserSetting = true;
laserOnOff.setText("Laser On");
} else {
timer.stop();
laserSetting = false;
laserOnOff.setText("Laser Off");
}
}
});
Finally, your Timer can calculate the Duration using Duration.between:
Duration elapsedTime =
Duration.between(timeOfLastButtonPress, Instant.now());
If you’re using Java 9 or later, you can extract the numbers from a Duration directly:
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Duration elapsedTime =
Duration.between(timeOfLastButtonPress, Instant.now());
laserOnTimeTF.setText(String.format("%02d:%02d:%02d",
elapsedTime.toHoursPart(),
elapsedTime.toMinutesPart(),
elapsedTime.toSecondsPart()));
}
});
In Java 8, you will need to calculate it yourself:
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Duration elapsedTime =
Duration.between(timeOfLastButtonPress, Instant.now());
laserOnTimeTF.setText(String.format("%02d:%02d:%02d",
elapsedTime.toHours(),
elapsedTime.toMinutes() % 60,
elapsedTime.getSeconds() % 60));
}
});
I need a delay in my JTable every time a row is added.
public void añadirNuevo(Procesos procesosArray){
for(int i=0;i<procesosArray.size();i++){
Object nuevo[]= {procesosArray.obtener(i).getNombre(),procesosArray.obtener(i).getTam()};
nuevoTbl.addRow(nuevo);
//DELAY
}
}
Use javax.swing.Timer
Setting up a timer involves creating a Timer object, registering one
or more action listeners on it, and starting the timer using the start
method. For example, the following code creates and starts a timer
that fires an action event once per second (as specified by the first
argument to the Timer constructor). The second argument to the Timer
constructor specifies a listener to receive the timer's action events.
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
}
};
new Timer(delay, taskPerformer).start();
You can use Thread.sleep method
public void añadirNuevo(Procesos procesosArray){
for(int i=0;i<procesosArray.size();i++){
Object nuevo[]= {procesosArray.obtener(i).getNombre(),procesosArray.obtener(i).getTam()};
nuevoTbl.addRow(nuevo);
try {
Thread.sleep(1000); // 1 second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
So, I basically need a command to run every 5 seconds, but the Timer doesn't work...
I tried so many different methods,
The only thing that works is the Thread.sleep(Milliseconds);
But that causes my whole game to stop working...
If I try using a timer, for example:
Timer timer = new Timer(1000, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Hey");
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
How can I get this timer to fire correctly?
You should pair java.util.Timer with java.util.TimerTask
Timer t = new Timer( );
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
System.out.println("Hey");
}
}, 1000,5000);
1000 means 1 second delay before get executed
& 5000 means will be repeated every 5 seconds.
To stop it , simply call t.cancel()
How do I make my Timer Task run more than once? This is really bothering me..
timer = new Timer();
timer.schedule(new Client(), 1000);
public void run() {
try {
System.out.println("sent data");
socketOut.write(0);
} catch (Exception e) {
// disconnect client on their side
Game.destroyGame();
timer.cancel();
timer.purge();
}
}
I want this timer to run for an infinite amount of time until the Exception occurs.
When the Javadoc says that it repeats with a specific delay, the delay is the initial delay before the TimerTask starts and not for how long the TimerTask will run. You can repeat the task every period milliseconds. Look at the schedule method. Below is a simple example that repeats every 2 seconds, indefinitely. In the example, the call:
timer.schedule(new RemindTask(seconds), 0, seconds * 1000);
tells timer to run the RemindTask every seconds seconds (*1000 because the time here is really in miliseconds), with an initial delay of 0 - i.e. start the RemindTask right away and then keep repeating at regular intervals.
import java.util.Timer;
import java.util.TimerTask;
public class Main {
static Timer timer;
static int i = 0;
class RemindTask extends TimerTask {
private int seconds;
public RemindTask(int seconds) {
this.seconds = seconds;
}
public void run() {
i+= seconds ;
System.out.println(i + " seconds!");
}
}
public Main(int seconds) {
timer = new Timer();
timer.schedule(new RemindTask(seconds), 0, seconds * 1000);
}
public static void main(String args[]) {
new Main(2);
System.out.format("Task scheduled.%n");
}
}
Looks like to me you're running a GUI program (I'm assuimg SWING, because your other question you were using SWING). So here's a bit of advice. Use a javax.swing.Timer for Swing program.
"How do I make my Timer Task run more than once? "
javax.swing.Timer has methods .stop() and .start() and .restart(). A basic implementation of the Timer object is something like this
Timer timer = new Timer(delay, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
// do something
}
});
timer.start();
You can do anything you want in the actionPerformed and it will fire an event every how many ever milliseconds you provide to the delay. You can have a button call .start() or .stop()
See this answer for a simple implementation of Timer imitating a sort of stop watch for a Boggle game
I want to implement a clock within my program to diusplay the date and time while the program is running. I have looked into the getCurrentTime() method and Timers but none of them seem to do what I would like.
The problem is I can get the current time when the program loads but it never updates. Any suggestions on something to look into would be greatly appreciated!
What you need to do is use Swing's Timer class.
Just have it run every second and update the clock with the current time.
Timer t = new Timer(1000, updateClockAction);
t.start();
This will cause the updateClockAction to fire once a second. It will run on the EDT.
You can make the updateClockAction similar to the following:
ActionListener updateClockAction = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Assumes clock is a custom component
yourClock.setTime(System.currentTimeMillis());
// OR
// Assumes clock is a JLabel
yourClock.setText(new Date().toString());
}
}
Because this updates the clock every second, the clock will be off by 999ms in a worse case scenario. To increase this to a worse case error margin of 99ms, you can increase the update frequency:
Timer t = new Timer(100, updateClockAction);
You have to update the text in a separate thread every second.
Ideally you should update swing component only in the EDT ( event dispatcher thread ) but, after I tried it on my machine, using Timer.scheduleAtFixRate gave me better results:
java.util.Timer http://img175.imageshack.us/img175/8876/capturadepantalla201006o.png
The javax.swing.Timer version was always about half second behind:
javax.swing.Timer http://img241.imageshack.us/img241/2599/capturadepantalla201006.png
I really don't know why.
Here's the full source:
package clock;
import javax.swing.*;
import java.util.*;
import java.text.SimpleDateFormat;
class Clock {
private final JLabel time = new JLabel();
private final SimpleDateFormat sdf = new SimpleDateFormat("hh:mm");
private int currentSecond;
private Calendar calendar;
public static void main( String [] args ) {
JFrame frame = new JFrame();
Clock clock = new Clock();
frame.add( clock.time );
frame.pack();
frame.setVisible( true );
clock.start();
}
private void reset(){
calendar = Calendar.getInstance();
currentSecond = calendar.get(Calendar.SECOND);
}
public void start(){
reset();
Timer timer = new Timer();
timer.scheduleAtFixedRate( new TimerTask(){
public void run(){
if( currentSecond == 60 ) {
reset();
}
time.setText( String.format("%s:%02d", sdf.format(calendar.getTime()), currentSecond ));
currentSecond++;
}
}, 0, 1000 );
}
}
Here's the modified source using javax.swing.Timer
public void start(){
reset();
Timer timer = new Timer(1000, new ActionListener(){
public void actionPerformed( ActionEvent e ) {
if( currentSecond == 60 ) {
reset();
}
time.setText( String.format("%s:%02d", sdf.format(calendar.getTime()), currentSecond ));
currentSecond++;
}
});
timer.start();
}
Probably I should change the way the string with the date is calculated, but I don't think that's the problem here
I have read, that, since Java 5 the recommended is: ScheduledExecutorService I leave you the task to implement it.
This sounds like you might have a conceptual problem. When you create a new java.util.Date object, it will be initialised to the current time. If you want to implement a clock, you could create a GUI component which constantly creates a new Date object and updates the display with the latest value.
One question you might have is how to repeatedly do something on a schedule? You could have an infinite loop that creates a new Date object then calls Thread.sleep(1000) so that it gets the latest time every second. A more elegant way to do this is to use a TimerTask. Typically, you do something like:
private class MyTimedTask extends TimerTask {
#Override
public void run() {
Date currentDate = new Date();
// Do something with currentDate such as write to a label
}
}
Then, to invoke it, you would do something like:
Timer myTimer = new Timer();
myTimer.schedule(new MyTimedTask (), 0, 1000); // Start immediately, repeat every 1000ms
public void start(){
reset();
ScheduledExecutorService worker = Executors.newScheduledThreadPool(3);
worker.scheduleAtFixedRate( new Runnable(){
public void run(){
if( currentSecond == 60 ) {
reset();
}
time.setText( String.format("%s:%02d", sdf.format(calendar.getTime()), currentSecond));
currentSecond++;
}
}, 0, 1000 ,TimeUnit.MILLISECONDS );
}
For those preferring an analog display: Analog Clock JApplet.
Note the method scheduleAtFixedRate is used here
// Current time label
final JLabel currentTimeLabel = new JLabel();
currentTimeLabel.setFont(new Font("Monospace", Font.PLAIN, 18));
currentTimeLabel.setHorizontalAlignment(JTextField.LEFT);
// Schedule a task for repainting the time
final Timer currentTimeTimer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
currentTimeLabel.setText(TIME_FORMATTER.print(System.currentTimeMillis()));
}
};
currentTimeTimer.scheduleAtFixedRate(task, 0, 1000);
Timer timer = new Timer(1000, (ActionEvent e) -> {
DateTimeFormatter myTime = DateTimeFormatter.ofPattern("HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
jLabel1.setText(String.valueOf(myTime.format(now)));
});
timer.setRepeats(true);
timer.start();