Java Swing timer does not do what I want it to - java

I need to write a program that uses a swing countdown timer to do something (in this case, print out a String in the console). It gets the needed delay info from a spinner and executes the code when I hit the Start button. However, when I enter a value in the spinner, it just waits for twice that many seconds and finishes the run without printing out anything.
private void StartActionPerformed(java.awt.event.ActionEvent evt) {
int x = (int) Spinner1.getValue() * 1000;
Timer TIMER = new Timer(x, new MyActionListener());
TIMER.start();
try {
Thread.sleep(x * 2);
} catch (InterruptedException e) {
}
TIMER.stop();
}
class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("Something");
}
}
Any help would be greatly appreciated!

The problem is that you are locking out yourself.
With
Thread.sleep(x * 2);
you are blocking the EventDispatchThread that would run your ActionListener. Still the timer internally keeps a flag that the timeout occured and that it should run your ActionListener at the next possible time.
But
TIMER.stop();
is resetting the TIMER, so that the notification is lost.

Related

Reuse a timer timertask Java

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);

Java - how to create delays

I'm wondering how can I make a Java program delay parts of code to prevent spamming buttons/other things in the program. So let's just say I'm making a program that displays the amount of times a user has clicked a button. I would like there to be a delay to the user cannot click the button rapidly. I heard that java timers could help me, but I can't find any tutorial explaining what I need done.
public void ButtonActionPerformed(java.awt.event.ActionEvent evt) {
count+=1;
labelA.setText(Integer.toString(count));
}
This is just an example program, not what im actually working on. So can someone please help me? I need to have a program create a delay so the user cannot spam buttons. Thanks :) (this is a revised question from before)
If you have a field timer of javax.swing.Timer,
private Timer timer;
you can create the instance in the constructor or a init method:
final ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(true);
}
};
timer = new Timer(2000, listener);
timer.setRepeats(false);
In this case, the delay is 2000 miliseconds before enabling the button again.
You can start it in the click event of the button.
button.setEnabled(false);
timer.start();
Save an instance variable in your action listener called long lastClicked and initialize it to 0.
in your handler:
int delay = 1000;
if(System.currentTimeMillis() > lastClicked + delay)
{
//do your click
lastClicked = System.currentTimeMillis();
}
A delay of 1000 would be 1 second.

strange behaviour of javax.swing.Timer

in main if the following code is used
Timer timer = new Timer(200, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("boo");
}
});
timer.start();
Thread.sleep(3000);
boo will be printed every 200 milliseconds as expected.
While
Timer timer = new Timer(200, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("boo");
}
});
timer.start();
nothing will be output!
Presumably the code you're showing is in main(). When main() returns, the program exits before the timer thread has a chance to get going. The sleep gives the JVM enough time to create the other thread, which then allows the JVM to keep running.
Could it be that the Thread.sleep is on the main thread and that the reason nothing is printed in the second case is that the main thread goes away and the program exits?
Is that the complete program (is that the only code in your main method)? If yes, then in the second case the program ends before the timer goes off, so it won't print anything, because the program is finished almost immediately.
1) this code wokrs and in all cases is correct
Timer timer = new Timer(200, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("boo");
}
});
timer.start();
you have to check if javax.swing.Timer#setRepeats() have true value (default value), if isn't changed, otherwise you have a code that block Event Dispatch Thread, thenafter Swing's Timer too,
2) don't use Thread.sleep(int) during EDT, and untill Sleep ended caused this code block for EDT,

Counter to Close JFrame, bring up Confirm Dialog

This post relates to my last one regarding a timer. I decided the easiest thing to do for immediate results was to just write a Counter thread that counts down from a certain time (in this case 5 seconds) and if the counter reaches 0, the JFrame closes and let's the user know that time has expired.
I'm running into some trouble, however. I cannot seem to make the JFrame close when the counter reaches 0. I'm not sure if I'm missing something stupid or if I am misunderstanding the way threads work and the way JFrames work. Here is the code, let me know what you think.
On a side note, I understand it would probably be most efficient to use a swing.Timer, but I just don't quite grasp the nature of them yet. I'm under self-imposed time constraints (I'm not a student or anything, I just like to stay motivated) and so I'm "jerry-rigging" this thing for now.
Anyway, on to the code!
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
public class RacerDoom extends JFrame {
boolean timesUp=false;
public RacerDoom() {
//create JFrame
super("Racer Doom Squared");
setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
if(timesUp==true) {
dispose();
JOptionPane.showConfirmDialog(null, "Time's Up! Click Okay to try again!");
}
Counter c1 = new Counter();
c1.start();
//Counter
private class Counter extends Thread {
public Counter() {}
public void run() {
for(int i=5;i>=0;i--) {
if(i==0) {
timesUp=true;
}
System.out.println(i);
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
}
}
}
...
EDIT: I have the timer implemented and working. It does exactly what I need it to, but I can't get the timer.stop(); command to work. I get the error "The local variable timer may not have been initialized.
Like I said, the timer works, it just never stops working until the program is terminated. Here is the constructor code for the JFrame, where the timer is located.
int counter = 0;
public RacerDoom() {
//create JFrame
super("Racer Doom Squared");
setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
final Timer timer=new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(counter>=10) {
timer.stop(); //the error occurs here
dispose();
JOptionPane.showConfirmDialog(null, "Time's Up!");
}
else{
counter++;
}
System.out.println(counter);
}
});
//inner thread
Move1 m1 = new Move1();
m1.start();
timer.start();
}
Thats easy to do with the help of a swing timer.. See this code sample:
final java.swing.Timer timer=new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(counter>5) {
timer.stop();
<dispose the fram here>
}else{
counter++;
}
}
});
timer.start();
I put this code in the constructor of my JFrame which will run in the Event despatch thread. If you dont want hang up your GUI, make sure that you run this timer on another thread and when you are disposing the JFrame wrap the call with SwingUtilities.invokeLater() - This ensures that the call gets queued on the event despatch thread.
I think your code is not working for the same reason, that you trying to something that does not get queued up in the event despatch thread. Here's an article that will get you going
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html

Stopping a Swing timer until the user clicks

I'm writing a card game. Right now I'm having problems with mouse handling. Below is the timer that handles the game flow of drawing and discarding cards.
final Timer timer = new Timer(1000, null);
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
b.players[p].drawCard();
if(p==0) // player zero is the human player
{
timer.stop();
// ...
b.players[p].discardCard(i);
timer.start();
}
else
b.players[p].discardCard(0);
p=(p+1)%4;
b.repaint();
}
});
The thing is that I want to stop the timer, wait until the user clicks the card he wants to discard, then start the timer again. b implements MouseListener in a basic way:
public void mouseClicked(MouseEvent arg0)
{
clickX = arg0.getX();
clickY = arg0.getY();
}
There's also the xYtoCardIndex() method somewhere out there.
What do I do here? I assume I have to do nothing in a nonblocking way, right?
In pseudo-code, in your MouseEventListener :
public void mouseClicked(MouseEvent arg0)
{
clickX = arg0.getX();
clickY = arg0.getY();
Card discarded = getCard(clickX,clickY);
b.players[p].discardCard(discarded);
// The card has been discarded, I can start my timer again.
timer.start();
}
In your drawCard function :
public void drawCard() {
// Stop the timer
timer.stop();
// Do the drawing.
}
This way, when the player draws a card, the timer stops until a card is discarded.
First, your code is not compiled:
b.players[p].discardCard(int i); contains a syntax error int i.
Second, I do not really understand the problem. Stop the timer when you want, implement your listener (i.e. mouse listener) that starts the timer.
Or probably I did not understand your question?
BTW I have just checked Timer API. It does not have neither start nor stop methods. You have to deal with specific tasks to control execution.

Categories