I am working on a board game, and in a part of the game, I need to have like this button which is when clicked, will change a label repeatedly counting 1 to 5 with 1 second delay interval, and after will change the label into "done", but the problem it changes the label into "done" first then the counting.
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
// #Override
public void run() {
count++;
if (count >= 6) {
timer.cancel();
timer.purge();
return;
}
lbl.setText(String.valueOf(count));
}
}, 1000,1000);
lbl.setText("done");
}});
When you click on the button, the actionPerformed() method is executed sequentially:
Create a new timer
Register a task to execute regularly each second, in the future
Set the button label to "Done"
Then, later, the timer do its job and will start to increase the variable count, updating each time the button label. Reading like this should help you to understand what is happening: the timer is executed in a separate thread. timer.scheduleAtFixedRate() is a non-blocking function, which registers a TimerTask to execute later, and returns immediately.
To fix your issue, something like that could be a solution:
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
// #Override
public void run() {
count++;
if (count >= 6) {
timer.cancel();
timer.purge();
// We set the label to done only when the counter
// reaches the value 6, after button displayed 5
lbl.setText("done");
return;
}
lbl.setText(String.valueOf(count));
}
}, 1000,1000);
}});
Related
I am trying to setup a program that enables the user to display a transition when clicking the next and previous button. When pressing next, the swing timer should trigger and start the animation. When transitioning, there should be a flag that states it is in the transition period. The Swing timer should fire once every tenth of a second and essentially last 1 second.
public class guiCreation {
static Timer timer;
static boolean flag = false;
private static void guiInterface() {
next.addActionListener(new ActionListener(){
timer = new Timer(1000, this);
public void actionPerformed(ActionEvent e){
nextGest();
}
});
//should go to the next tab
previous.addActionListener(new ActionListener(){
//if the list gets to the beginning, disable button
public void actionPerformed(ActionEvent e){
prevGest();
}
});
}
public static void nextGest() {
timer.start();
previous.setEnabled(true);
next.setEnabled(true);
//if the list gets to the end, disable button
if (cardLayout.isNextCardAvailable()) {
status.setText(" Next button has been clicked");
//System.out.println("This is the" + size);
cardLayout.next(cardPanel);
next.setEnabled(cardLayout.isNextCardAvailable());
}
}
public static void prevGest() {
if (cardLayout.isPreviousCardAvailable()) {
timer.start();
next.setEnabled(true);
previous.setEnabled(true);
status.setText(" Previous button has been clicked");
cardLayout.previous(cardPanel);
previous.setEnabled(cardLayout.isPreviousCardAvailable());
}
}
}
This: "The Swing timer should fire once every tenth of a second ..." -- does not agree with this: timer = new Timer(1000, this); Your Timer is firing once every second, not every 10th of a second.
Instead, you should:
Create a new Timer(100, ...), one that fires every 10th of a second
Store in an instance field the start time in msecs when the Timer begins (likely do this in your button's ActionListener)
Within the Timer's ActionListener get the current mSecs and use this to check the elapsed time
Stop the Timer via ((Timer) e.getSource()).stop(); once 1 full second has elapsed
No need for a flag, since all you need to do is to check if the Timer isn't null and if it .isRunning(). e.g., if (timer != null && timer.isRunning()) { -- then the animation is proceeding.
Unrelated suggestion:
Get out of the static world and into the instance world. You're programming in Java, a language that is built to use OOPs from the ground up, and you don't want to fight against the OOPs paradigm.
I have a game method that has Timer inside this method, only for some specific case(if condition below) i wanna stop timer...But for some reason it is causing me a crash.
public model() {
public game() {
Timer timer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
....
//draw shapes on JFrame
if (model.Life == 0) { //specific condition
model.timer.stop(); //timer is making a crash here
}
repaint();
}
});
timer.start();
}
The Timer is the source of the ActionEvent so you can just do:
if (your condition)
{
Timer timer = (Timer)e.getSource();
timer.stop();
}
This way you don't have to worry about keeping an instance variable for the Timer.
I have one button include timer, but when I clicked the button again, same timer start counting twice. I want to stop the counter every time and restart it. how can I do it?
#FXML
private void handleButtonAction(ActionEvent event) {
int cnt=0;
Timer timer=new Timer();
TimerTask task=new TimerTask() {
#Override
public void run() {
cnt++;
System.out.println("task: "+cnt);
}
};
timer.schedule(task, 0, 3000);
}
when I clicked the button again, it calls system out twice.
By calling Timer timer = new Timer(); inside handleButtonAction you create a new Timer with every click.
You have to declare the Timer outside the method, then you can restart it by clicking the button like:
Timer timer;
private void handleButtonAction(ActionEvent event) {
int cnt=0;
timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
cnt++;
System.out.println("task: "+cnt);
}
};
timer.schedule(task, 0, 3000);
}
This way you always restart the same timer.
Soo created a timer using extending timertask.
label_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
label_1.setVisible(false);
label_2.setVisible(true);
timer.purge();
class MyTimeTask extends TimerTask
{
public void run(){
genReelNumbers();
laa++;
if(laa==50){
timer.cancel();
timer.purge();
laa=0;
label_1.setVisible(true);
label_2.setVisible(false);}}}
timer.purge();
timer.schedule(new MyTimeTask(), 0, 50);}});
But im getting a error with the timer already canceled! As you can see i already tried to use the purge(), soo it cancels the "canceled" timers (dont know if that does make any sence). I want to use this timer each time that i press on the label! Any ideas?
First and foremost, this looks to be a Swing application, and if so, you shouldn't be using java.util.Timer and java.util.TimerTask since Swing is single-threaded, and the two classes above create a new thread or threads to achieve their actions, meaning that important code that should be called on the Swing event thread will not be called on this thread. This this risks causing pernicious intermittent and hard to debug threading exceptions to be thrown. Instead use a javax.swing.Timer. Then to stop this timer, simply call stop() on it, and to restart it, simply call start() on it. For more on this, please read: How To Use Swing Timers.
For example, I'm not 100% sure what you're code is supposed to be doing, but it could look something like:
// warning: code not compile- nor run-tested
label_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
label_1.setVisible(false);
label_2.setVisible(true);
// assuming a javax.swing.Timer field named timer
if (timer != null && timer.isRunning()) {
// if the timer is not null and it's running, stop it:
timer.stop();
}
// TIMER_DELAY is an int constant that specifies the delay between "ticks"
timer = new Timer(TIMER_DELAY, new ActionListener() {
#Override // this method will be called repeatedly, every TIMER_DELAY msecs
public void actionPerformed(ActionEvent e) {
genReelNumbers();
laa++;
if(laa==50){
timer.stop();
// timer.purge();
laa=0;
label_1.setVisible(true);
label_2.setVisible(false);
}
}
});
timer.start();
}
});
after canceling the timer you have no other choice than creating a new object....
I followed the #Hovercraft advice and changed to javax.swing.Timer
It turned out like this:
//The variable "taxa" is the amount of times that i want it to do the task
javax.swing.Timer time1 = new javax.swing.Timer(taxa, new ActionListener() {
public void actionPerformed(ActionEvent e) {
genReelNumbers();
}
});
//starts the timer
time1.start();
//New timertask
TimerTask tt = new TimerTask() {
#Override
public void run() {
//stops the timer
time1.stop();
label_2.setVisible(false);
label_1.setVisible(true);
verificarodas();
}
};
Timer time = new Timer(true);
// the 2000 is how long i want to do the task's
//if i changed to 3000 it would take 3 seconds (remember it has to be a value on miliseconds) to do the 15 times, and soo on
time.schedule(tt, 2000);
I am implementing a timer:
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
//Do something;
}
},1000,1000);
But, I would like to have a timeout so that after lets say 100 tries/ 10 seconds, the timer stops automatically.
Thanks.
try
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
int n = 0;
#Override
public void run() {
System.out.println(n);
if (++n == 5) {
timer.cancel();
}
}
},1000,1000);
You can simply have a variable outside the run method that keeps count of the iteration. Make an if statement inside the run() method that cancels the timer when it hits your desired amount. Increase the variable by one everytime the run() method executes.
start another timer, as soon as above timer starts, which cancels the above timer after 10sec. check to code below as a quick solution. but better you cancel the task() instead of timer.
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
timer2.schedule(new TimerTask() {
#Override
public void run() {
timer1.cancel();
}
},0);
//Do something;
}
},1000,1000);
timer2 = new Timer();
I dont think we have java API for this in Timer class. You need to do it programmatically by implementing some custom logic based on your requirement.