I've created a javafx application which includes a time-tracking function that tracks the amount of time the application has been open(run) for. I know about System.currentTimeMillis(), but I was wondering if it was possible to create a button (that serves no function as a button - I just needed to use a JFX button which looks nice) that shows(prints) the amount of time spent in the app. Something like a real-time counter where the time increases by itself.
Something similar to this: https://www.youtube.com/watch?v=f8LOflGG8g8
Except, however, instead of using animations, using text instead.
Just use an AnimationTimer to update the text:
public class MyApp extends Application {
#Override
public void start(Stage primaryStage) {
long startTime = System.currentTimeMillis();
Label timerLabel = new Label();
new AnimationTimer() {
#Override
public void handle(long now) {
long elapsedMillis = System.currentTimeMillis() - startTime ;
timerLabel.setText(Long.toString(elapsedMillis / 1000));
}
}.start();
// lay out UI etc etc
}
}
Create a Thread class
Start it whenever you like, and pass the current time as an argument to the above class (System.currentTimeMillis())
Inside the thread, have a loop, and a Thread.sleep(1000); at the end. Every time the loop goes, have it subtract the time you passed along in step 2 from the current time like this: System.currentTimeMillis() - startTime
Use the proper async GUI update methods to update the button you want. You can divide your calculated time by 1000 to get the seconds, another 60 to get the minutes, and another 60 to get the hours.
Related
I have two threads in my ChessGame and I want to implement time control:
Turn of first player: second_thread.stop(), first_thread.run();
counterOfSteps++;
Turn of second player: first_thread.stop(), second_thread.run();
counterOfSteps++;
I have founded many information about Timer but I need Threads.Second thread the same.
There is my code of first thread and it doesn't work because time isn't stopped (System.currentTimeMillis)
first = new Thread() {
#Override
public void run() {
final long time = System.currentTimeMillis();
final long duration = 10800000; //3 hours
while (true) {
try {
Thread.sleep(100);
if (counterOfSteps % 2 == 0) {
System.out.println("Time" + ((duration - (System.currentTimeMillis() - time)) / 1000) % 60);
}
} catch (InterruptedException ex) {
LOG.log(Level.SEVERE, "Unexpected interrupt", ex);
}
}
}
};
How to solve this problem?
Update:
I don't use .stop(). I wrote is for example how to realize.
I have founded many information about Timer but I need Threads.
No. If all you are trying to do is implement a chess clock, then you don't need threads for that. A Timer task that wakes up every second (or every 1/10 second) can;
look at whose turn it is (e.g., counterOfSteps % 2),
compute how much time that player has used, and
Update the appropriate text box in the GUI.
To compute how much time, it'll need to know three things;
What time it is now (e.g., System.currentTimeMillis()),
What time it was when the current turn started, and
How much time the player already had on the clock when the current turn started.
There is no way to pause the system clock (i.e., System.currentTimeMillis()), but that's not a problem. If you sample the clock at the start of each turn, then you can compute the duration of the current turn as System.currentTimeMillis() minus the start time.
I used this example for my quiz, i have 10sec do answer on question this timer decrease int t every 1sec, and set how many times left in some JLabel. You can make 2 object of Timer, first object for first player and second object for second player. You can stop timer when someone finish the move and start second timer...
int t=10
lb2=new JLabel(t);
tim=new Timer(1000,new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
if(t>0){
t--;
lb2.setText(String.valueOf(t));
}else{
tim.stop();
JOptionPane.showMessageDialog(null, "Time is up");
}
}
});
}
I have to show multiple clocks in screen from different places like New Delhi, Hong Kong, Frankfurt, Washington, etc. And these times are changing like any other real clock but as Time-Left to a fixed date-time and they are added to the screen at different moments as the user adds them. For example:
New Delhi 1d 4h 20 min 5s
Hong Kong 9h 2min 55s
Washington 22min 3s
...
I have a Class which makes all the calculations to get those times in that format. The problem comes when these times are shown on screen. How do I make them to update their time at the same time? So all the changes in the seconds are shown at the same time. I know it won't be theoretically at the same time, but the most close to it. This is the timer I am using:
Timer t = new Timer();
t.scheduleAtFixedRate(
new TimerTask()
{
public void run() {
Platform.runLater(new Runnable() {
#Override
public void run() {
label[id].setText(getTimeLeft(id));
}
});
}
},
0, // run first occurrence immediately
1000); // run every seconds
Also, some of them freeze eventually. Does any body knows why?
How do I make them to update their time at the same time? So all the changes in the seconds are shown at the same time. I know it won't be theoretically at the same time, but the most close to it. This is the timer I am using:
Instead of using separate Timers for each label, use a single Timer for ALL the labels
Timer t = new Timer();
t.scheduleAtFixedRate(
new TimerTask()
{
public void run() {
Platform.runLater(new Runnable() {
#Override
public void run() {
for (int id = 0; id < label.length; id++) {
label[id].setText(getTimeLeft(id));
}
}
});
}
},
0, // run first occurrence immediately
1000); // run every seconds
This will reduce the overhead of resources on you system (one timer instead of n times), possible event queue spamming as multiple timers trigger simultaneously and allow the times to "seem" to update at the same time, as they are all updated within the event queue, so they won't update until the next paint cycle, which won't happen until you exit the run block...
You could also make use Timeline, which would reduce the need for Platform.runLater, see How to update the label box every 2 seconds in java fx? for an example.
I done simple timer that count the difference between time of clicking of button, and current time. Every second (1000ms).
The main part is :
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
MainActivity.this.timerHandler.postDelayed(this,1000);
long mlSecondToGo;
mlSecondToGo = System.currentTimeMillis() - MainActivity.this.clickedButtonTime;
MainActivity.this.timerTextView.setText(Long.toString(mlSecondToGo));
}
};
Whole code : https://gist.github.com/anonymous/7830279
I wonder why it the "1000ms" delay of the handler:
MainActivity.this.timerHandler.postDelayed(this,1000);
is delayed of 1-3 every time I call it.
I mean the TextView shows:
1001 then 1002 then 3004 and so on.
I made the video of it (using of Android's 4.4 screenrecord command from ADB)
http://youtu.be/TyFyS6k5L5c
Thank you very much for an answer.
I made CountDown.java file and try to add in my Word-trouble.java file (which is main applet) as CountDown ct = new CountDown();
but it is not showing timer in main applet.
Here is coding:
package pack.urdu;
import java.awt.*; //windows toolkit
import java.applet.*; //applet support
public class CountDown extends Applet implements Runnable{
int counter; Thread cd;
public void start() { // create thread
counter = 60; cd = new Thread(this); cd.start();
}
public void stop() { cd = null;}
public void run() { // executed by Thread
while (counter>0 && cd!=null) {
try{Thread.sleep(1000);} catch (InterruptedException e){}
--counter; repaint(); //update screen
}
}
public void paint(Graphics g) {
g.drawString(String.valueOf(counter),25,75);
}
}
You are making a mistake that I see a lot of programmers make: you are mixing up the calculation of elapsed time, with the calculation of the refresh time. If the duration of sleep takes long than a second because of thread contention, your timer will drift.
Instead of tracking a counter that increments every second, just record the start time:
long startTime = System.currentTimeMillis();
Then later, your paint method becomes:
public void paint(Graphics g) {
int elapsedSeconds = (int)(System.currentTimeMillis()-startTime)/1000
g.drawString(String.valueOf(elapsedSeconds),25,75);
}
This method can be called as often, and as many times as you like, and it will always display the correct elapsed seconds. There is no need to increment anything at any specified time.
The only other thing you have to do is to arrange that the screen gets refreshed. (I like to say that you only have to refresh the screen when the user looks at it :-) but since we don't know that we need to refresh more often). The mechanism for this may depend upon the graphic library. One lazy idea is to refresh ten times a second and the screen will be right most of the time.
If you do want to have a thread that sends repaint events, you should have those events sent just at the time that timer clicks over to a new value, and thereby send only one per second. This is done with:
while (stillRunning) {
long elapsedTime = System.currentTimeMillis() - startTime;
long timeTillNextDisplayChange = 1000 - (elapsedTime % 1000);
Thread.sleep(timeTillNextDisplayChange);
repaint();
}
Note that you do not sleep 1000ms! If your system is performing well, this will be very close to 1000ms, but slightly less than that to account for (1) the thread startup delay, possibly caused by thread contention, and (2) the processing time for this loop (which is quite small). In any case, calculating the sleep in this way will prevent timer drift, and assure that your display updates just as the seconds value changes.
See an extended discussion of Common Misunderstandings of Timers on my website.
I'm trying to write a blackberry app that is basically a stopwatch, and displays lap times. First, I'm not sure I'm implementing the stopwatch functionality in the most optimal way. I have a LabelField (_myLabel) that displays the 'clock' - starting at 00:00. Then you hit the start button and every second the _myLabel field gets updated with how many seconds have past since the last update (should only ever increment by 1, but sometimes there is a delay and it will skip a number). I just can't think of a different way to do it - and I am new to GUI development and threads so I guess that's why.
EDIT: Here is what calls the stopwatch:
_timer = new Timer();
_timer.schedule(new MyTimerTask(), 250, 250);
And here is the TimerTask:
class MyTimerTask extends TimerTask {
long currentTime;
long startTime = System.currentTimeMillis();
public void run() {
synchronized (Application.getEventLock()) {
currentTime = System.currentTimeMillis();
long diff = currentTime - startTime;
long min = diff / 60000;
long sec = (diff % 60000) / 1000;
String minStr = new Long(min).toString();
String secStr = new Long(sec).toString();
if (min < 10)
minStr = "0" + minStr;
if (sec < 10)
secStr = "0" + secStr;
_myLabel.setText(minStr + ":" + secStr);
timerDisplay.deleteAll();
timerDisplay.add(_timerLabel);
}
}
}
Anyway when you stop the stopwatch it updates a historical table of lap time data. When this list gets long, the timer starts to degrade. If you try to scroll, then it gets really bad.
Is there a better way to implement my stopwatch?
Here are a few tips:
keep track of the last "sec" value used to update the label, and exit from the run loop immediately if the newly-calculated "sec" value is the same - otherwise you're needlessly refreshing the UI with the same values which slows everything down
remove the synchronization in your run loop and just put the code that modifies the UI (setText call) in a UiApplication.getUiApplication.invokeLater() call (using an anonymous Runnable)
don't delete the re-add the label from the screen or maanger, you just need to call setText() and it should update - if it doesn't update then call invalidate() on the field and it will be redrawn
now that you've optimized your code and minimized the amount of actual UI drawing, it's safe to set the timertask interval to a lower value, such as 50ms, so that you have a smoother timer update
The most important thing to remember in making a fast UI is to only update the UI when you need to, and only update the fields that need to change. If you're calling methods like deleteAll() you're going to end up having the entire screen or manager refresh which is really really slow.