I'm trying to implement a countdown timer into a pre-existing public class and I have a few questions.
An overview: I want to have a timer within a program that counts down from 60 (seconds) once the program is initialized.
If the timer reaches zero, the program quits.
If the user meets certain parameters within the 60 second time frame, the timer resets to 60, presents a new set of parameters, and begins the countdown again. It should be able to do this an infinite number of times, until the user fails to meet parameters within 60 seconds.
There will also be some sort of (TBD) GUI representation of the timer, most likely either numerical countdown or JProgressBar.
I'm semi-new (~3 months) to programming, self-taught, and still learning lots (so be gentle) :)
My questions are:
What is the best way to implement this?
I'm assuming this needs to run in a thread?
Will the timer be easily configurable? (not important, just interesting)
Thanks for your help. If you need to see code, I can find some.
EDIT: Just for some clarification/context:
This is for a timed racing video game I'm working on to develop my skills as a programmer. The idea is that a player has 60 seconds to complete a lap. If the player completes a successful lap, the timer resets to 60 seconds and the track changes to be slightly more difficult. The game runs until the player is unable to complete a lap in 60 seconds due to the difficulty. The game records the number of laps as a high score, and asks to player if they would like to try again.
If I were you, I'd use:
an AtomicInteger variable which would keep the current countdown value;
a timer thread that would wake up every 1s and decrementAndGet() the variable, comparing the result to zero and terminating the app if the result is zero;
(possibly) a thread that would also wake up every 1s to repaint the GUI -- the best approach here depends on your GUI framework.
Finally, whenever you need to reset the count back to 60s, you just call set(newValue) from any thread.
The timer thread's run() method could be as simple as:
for (;;) {
if (counter.decrementAndGet() <= 0) {
// TODO: exit the app
}
Thread.sleep(1000);
}
I think it's much easier to get this right than trying to manage multiple Timer objects.
The best way to impliment timer in your application is using some sheduler frameworks like Quartz
You could use java.util.Timer to schedule an execution of a method and then cancel it if the requirements is met.
Like this:
timer = new Timer();
timer.schedule(new Task(), 60 * 1000);
And then make a class like this to handle the timerschedule:
class Task extends TimerTask {
public void run() {
System.exit(0);
}
}
If the requirements is met, then do this to stop it from executing:
timer.cancel();
If you need to update your GUI better to use SwingWorker http://en.wikipedia.org/wiki/SwingWorker
I would write something like this:
SwingWorker<String, Integer> timer = new SwingWorker<String, Integer>() {
Integer timer=60;
#Override
protected String doInBackground() throws Exception {
//update guiModel
//label.setText(timer.toString());
while(timer>0){
Thread.sleep(1000);
timer--;
}
return null;
}
#Override
public void done(){
System.exit(0);
}
};
JButton restart = new JButton(){
{
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.cancel(true);
timer.execute();
}
});
}
};
Related
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 have an if statement which evaluates the time since the program has begun running and if the time is above a certain threshold, does something. I want this if statement to be checked throughout the whole time the program is running while at the same time have the program continue execution. How would I go about doing this?
Thank you.
The easiest approach would be to use a Timer. With that, you don't need the if logic; you can just use the firstTime argument when scheduling a TimerTask.
Timer timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
// do something
}
};
// schedule the task to be run every 100ms (0.1 sec),
// starting after "threshold" milliseconds have past
timer.schedule(task, threshold, 100);
It's not clear from your description if you want to repeatedly "do something" once the time threshold has been exceeded, or if you just want to wait until a certain time has passed and then "do something" once. The above code is for the repeating case. For a one-shot occurrence at some future time, change the last line to:
timer.schedule(task, threshold);
If you're using Swing, you should use a Swing Timer rather than a java.util.Timer. See How to Use Swing Timers for more info.
EDIT: Your comment clarified things a bit. It's fairly easy to do what you described:
Timer timer = new Timer();
TimerTask task = new TimerTask() {
private final long start = System.currentTimeMillis();
#Override
public void run() {
if (System.currentTimeMillis() - start < threshold) {
// do something
} else {
// do something else
}
}
};
// schedule the task to be run every 100ms (0.1 sec), starting immediately
timer.schedule(task, 0, 100);
Note that "do something" and "do something else" can be method calls to an enclosing class.
A cleaner approach might be to define several TimerTasks that are scheduled to execute at different times. The "something else" task that triggers an exception can be scheduled for one-time execution at the threshold time. You can also cancel individual tasks and you can even schedule a task that will cancel another task.
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 would like to know how should I implement a count down timer in swing.
I'm currently developing a net game with count down timer, and I need the Timer to be shown all the time in the corner.
The problem is I don't know how to implement it in away that the game screen will be responsive all the time for the user in the same time the timer is on..
1.I'm asking it because I know every update to the view is being held through the event dispatch thread but it can also freeze my game if there is something which run there consistently (like timer).
2.Design aspect :Do you know some nice ways of how to show the timer in an attractive and maybe animated way?
Thank you very much in advance
Use the javax.swing.Timer class. This will fire action events at fixed intervals, which will prevent the GUI from becoming unresponsive.
As for animation, see the 2D Graphics tutorial.
int j=10;
final Timer t = new Timer(1000, new ActionListener() {
private long time = 10 * 1000; //10 seconds, for example
public void actionPerformed(ActionEvent e) {
if (time > 0) {
time -= 1000;
j--;
jLabel1.setText(Long.toString(j));
}
}
});
t.start();
In our class we are making a game. The user has to Guess words and stuff. I don't think info about the game is needed to answer my question/problem.
Ok so what I am trying to do is to give the user a time limit in which they have to guess the word. Something like 15 seconds. If the user does not guess the word in 15 seconds they lose a turn.
Problems:
We didn't learn how to use timers. I experiment with timers and stuff. I can get a timer to count down from 15.
I can't check the current time while waiting for the user to input a guess.
I don't know how to bypass Stdin.readString() and make the program check the time.
Thanks.
Well, you can use the Scanner class to gather input from the user.
You may want to avoid timers if you don't know what threading is yet, but if you do want to try, you might be interested looking into the TimerTask & Timer classes.
While you may already know, you can get time from the System class, like currentTimeMillis
You have a few options. As you said, your program is waiting for input and hence that thread is busy. What you can do is create a separate thread, pass your timer to that thread and have it check the timer. Perhaps something like the following:
public class TimerChecker implements Runnable {
private Timer timer;
public TimerChecker(Timer timer) { this.timer = timer; }
#Override
public void run() {
// implement logic here
}
}
Which you can have invoked in a new thread using:
Timer timer = ...
new Thread(new TimerChecker(timer)).start();
// Now you are free to perform your blocking operation in the current thread
Stdin.readString();
One way to do this is, well to a run a separate thread object for the timer... this thread shall handle the updating of the time and would then trigger a certain event when the time of the player runs out...
or more like, implementing a counter in a separate thread whose increments are triggered by time-step, in this case, in seconds, you can do this by calling sleep()..
the timer thread object shall maintain a variable which keeps track of the current time..
on the main method of your program, you shall continue to check the value of this variable, as a pre-condition of your main loop perhaps,
the idea is there i think, just a thought!
pseudocode
class Timer extends Thread{
int current_time = 0;
public void run(){
sleep(1000);
current_time += 1;
}
public void synchronized getCurTime(){
return current_time;
}
}
class Game{
public Game(){
Timer timer = new Timer();
timer.start();
while (timer.getCurTime() <16){
//get the guess of the user
//checks if it's correct
// if it is correct, output you win and break!
}
//time runs out
}
}
How about an Event driven architecture with Java eventing library?
Example of events with conditions.