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));
}
});
Related
Hello I would like to ask for any advice on this problem.
I would like to display current time in HH:MM:SS format (refreshing every second) in label or whatever component that is good for it.
Any advice?
EDIT: Someone asked for a code.. so I put it here for better description of the problem. "I have no code for that time What I'm trying to achieve is simple GUI diary and in one of the labels I would like to display time remaining until the closest event and in the other label I want to display like clocks that refreshes every second. I need it to get remaining time working. All I can think of is creating new thread that will do it and refreshes the clock, but I am not that advanced to use multithreading in JavaFX . So I was wondering if anyone can advice me with something less complicated than multithreading (I dont know how to implement that thread into JavaFX components)"
Version with Timeline:
long endTime = ...;
Label timeLabel = new Label();
DateFormat timeFormat = new SimpleDateFormat( "HH:mm:ss" );
final Timeline timeline = new Timeline(
new KeyFrame(
Duration.millis( 500 ),
event -> {
final long diff = endTime - System.currentTimeMillis();
if ( diff < 0 ) {
// timeLabel.setText( "00:00:00" );
timeLabel.setText( timeFormat.format( 0 ) );
} else {
timeLabel.setText( timeFormat.format( diff ) );
}
}
)
);
timeline.setCycleCount( Animation.INDEFINITE );
timeline.play();
Label main_clock_lb = new Label();
Thread timerThread = new Thread(() -> {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
while (true) {
try {
Thread.sleep(1000); //1 second
} catch (InterruptedException e) {
e.printStackTrace();
}
final String time = simpleDateFormat.format(new Date());
Platform.runLater(() -> {
main_clock_lb.setText(time);
});
}
}); timerThread.start();//start the thread and its ok
One might find helpful how to print date and time for javaFx.
final Label clock = new Label();
final DateFormat format = DateFormat.getInstance();
final Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1),
new EventHandler()
{
#Override
public void handle(ActionEvent event)
{
final Calendar cal = Calendar.getInstance();
clock.setText(format.format(cal.getTime());
}
});
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
To solve your task using Timer you need to implement TimerTask with your code and use Timer#scheduleAtFixedRate method to run that code repeatedly:
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
System.out.print("I would be called every 2 seconds");
}
}, 0, 2000);
Also note that calling any UI operations must be done on Swing UI thread (or FX UI thread if you are using JavaFX):
private int i = 0;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
jTextField1.setText(Integer.toString(i++));
}
});
}
}, 0, 2000);
}
In case of JavaFX you need to update FX controls on "FX UI thread" instead of Swing one. To achieve that use javafx.application.Platform#runLater method instead of SwingUtilities
final Label clock = new Label();
final DateFormat format = DateFormat.getInstance();
final Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1),
new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
final Calendar cal = Calendar.getInstance();
clock.setText(format.format(cal.getTime()));
}
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
I have problem that I don't understand, how to correctly use the Java timer with JButton.
The idea of what I need -
When I click on JButton with text "0" then starts the timer counting from two seconds till zero.
When button is released program checks the situation:
if timer now is 0 then it shows in JTextField sign "+", else it shows "0".
Here is my code of program. Can someone please add the things that I need to make the program work like the idea I want?
public class DialPanel extends JPanel {
private MainFrame frame;
public DialPanel(MainFrame frame) {
this.frame = frame;
this.setLocation(0, 90);
this.setSize(300, 290);
this.setLayout(null);
this.setBackground(color);
this.initContent();
}
// -------------------------------------------------------------------------
private JButton btnNumZero;
private JTextField txfNumber;
private void initContent() {
txfNumber = new JTextField();
this.add(txfNumber);
txfNumber.setSize(190, 30);
txfNumber.setLocation(30, 0);
txfNumber.setFocusable(false);
txfNumber.addActionListener(controller);
btnNumZero = new JButton();
this.add(btnNumZero);
btnNumZero.setText("0");
btnNumZero.setFocusable(false);
btnNumZero.setSize(30, 30);
btnNumZero.setLocation(10, 10);
btnNumZero.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
//Start someTimer countdown from two seconds
}
});
btnNumZero.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
//Stop someTimer
//if someTimer == 0 seconds then do this line:
txfNumber.setText("+");
//else do this line:
txfNumber.setText("0");
}
});
}
}
Excuse me if there is some unnecessary error with code. I deleted and changed a lot of things from the real one code so that this could be more understandable and clear for reading.
Instead of using a Timer, you may want to just make use of System.currentTimeMillis(). The Timer may not be a timer in the sense you are looking for, as a stopwatch type object.
You could do something like this
long startTime;
long endTime;
btnNumZero.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
startTime = System.currentTimeMillis();
}
});
btnNumZero.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
endTime = System.currentTimeMillis();
long difference = endTime - startTime;
if (difference > 2000)
txfNumber.setText("+");
else
txfNumber.setText("0");
}
});
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.
I am making a simple target shooting game.I have a countdownTimer inside the label and an object that blinks in a random position inside the panel. Every time I click on the object,. the object's timer stops which makes that object stop too, but the countdown timer doesn't and that is my problem. I want the countdown timer should stop also.
Could someone help me about this matter?
Here's the code :
private void starting()
{
new Timer(TIMER_PERIOD, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
if (count++ < MAX_COUNT)
{
String text = "Time remaining: (" + (MAX_COUNT - count) + ") seconds left";
setCountDownLabelText(text);
Date date = new Date();
setCountDownPanelText(date);
}
else
{
((Timer) e.getSource()).stop();
randomTimer.stop();
JOptionPane.showMessageDialog(null, "Game Over");
System.exit(0);
}
}
}).start();
}
It strikes me that you don't understand the code at all, that you are unaware of the anonymous class created that is extending Timer, which (if you'd seen the documentation) has a function stop() which does what you ask.
You need to store a reference to the Timer.
private javax.swing.Timer timer;
private void starting() {
timer = new Timer(TIMER_PERIOD, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
// do stuff
// stop the timer
timer.stop();
// do other stuff
}
}
}
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();