JAVA SWING - Creating Animation using Swing Timer - java

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.

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

JDialog doesn't dispose

I'm new into programming and I'm having some trouble with this.
The problem is, I'm using the Swing palette to create an assignment where I'm using a JDialog to display a timer at the same time of another frame, when I dispose this frame to change to another and return to the previous one the timer in the JDialog overlaps the first one that was running, and I couldn't managed to fix it.
Here's the code.
MAIN
public static void main(String[] args) {
Panel0 screen=new Panel0();
screen.setTitle("");
screen.setLocationRelativeTo(screen);
screen.setVisible(true);
}
1st FRAME
public class Panel0 extends javax.swing.JFrame {
Panel s=new Panel();
private void fisica1ActionPerformed(java.awt.event.ActionEvent evt) {
s.time();
s.setTitle("FISIC I");
s.setLocationRelativeTo(s);
s.setVisible(rootPaneCheckingEnabled);
s.dialog.setVisible(rootPaneCheckingEnabled);
dispose();
}
2nd FRAME
public class Panel extends javax.swing.JFrame {
private void EndActionPerformed(java.awt.event.ActionEvent evt) {
dialog.dispose();
dialog.setDefaultCloseOperation(0);
Panel0 pan=new Panel0();
pan.setLocationRelativeTo(p1);
pan.setVisible(rootPaneCheckingEnabled);
dispose();
}
void time(){
t=new Timer(1,new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (startTime<0) {
startTime=System.currentTimeMillis();
}
long now = System.currentTimeMillis();
long clockTime = now - startTime;
if (clockTime >= duration) {
clockTime = duration;
t.stop();
}
SimpleDateFormat sdf=new SimpleDateFormat("mm:ss:SS");
clock.setText(sdf.format(duration-clockTime));
}
});
t.setInitialDelay(0);
if (!t.isRunning()) {
startTime = -1;
t.start();
}
}
I omitted the inizialization of the Timer and such, because I don't think that's the problem.
To clarify something: Once I close the 2nd frame the 1st opens and gives me options to repeat this process over and over, and everytime the JDialog named "dialog" overlaps with its data (you can see the numbers of the clock overlaping).
dispose() does not means that you will "destroy" the object or clear its state. It means that you will release graphics resources attached to that frame (low level window handle and stuff). It still can be reused with setVisible(true)
I assume that you want to reuse our popup - this is just fine, but I think that you are forgetting to stop the "disposed" timer thus every new timer you create on action will be exposed to so called "racing conditions".
Timers are simple background task and they must be stopped explicitly - it will not be done by itself.
Every call to s.time(); starts new timer without stopping previous one.
Simply speaking: you have multiple timers updating the same text field.
Solution: Stop previous timer before running new OR restart previous timer.

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.

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.

How to create a dialogbox that will pop up after 5 minutes of idleness by the user? (java)

I have a dialog box that is:
JOptionPane.showMessageDialog(null,"Once medicine is given, measure temperature within 5 minutes." ,"Medication" ,JOptionPane.PLAIN_MESSAGE);
When the user presses 'ok', it goes straight to a Jframe that ask the user to input the temperature using a slider and then pressing a button that takes it to the next set of things.
Anyways, I want to create somekind of inivisble countdown after the user presses 'ok', so after 5 minutes of idleness on the Jframe menu, one warning dialog box should appear on top of the JFrame and says something like "NEED ATTENTION".
This reminds me of actionListener. but it will be invoked by non-physical element, 5 minutes, (not by any click of button).
So Maybe the code should be like:
JOptionPane.showMessageDialog(null,"Once medicine is given, measure temperature within 5 minutes." ,"Medication" ,JOptionPane.PLAIN_MESSAGE);
temperature_class temp = new temperature_class(); // going to a different class where the the Jframe is coded
if (time exceeds 5 minutes) { JOptionPane.showMessageDialog(null, "NEED attention", JOptionPane.WARNING_MESSAGE);}
else { (do nothing) }
Code works:
JOptionPane.showMessageDialog(null,"measure temp" ,"1" ,JOptionPane.PLAIN_MESSAGE);
int delay = 3000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
JOptionPane.showMessageDialog(null,"hurry." ,"Bolus Therapy Protocol" ,JOptionPane.PLAIN_MESSAGE); } };
new Timer(delay, taskPerformer).start();
temperature_class temp = new temperature_class();
However, I want it do it only once. So how do I invoke set.Repeats(false)?
You could use a TimerTask with a Timer:
class PopTask extends TimerTask {
public void run() {
JOptionPane.show...
}
}
then where you want to schedule your task:
new Timer().schedule(new PopTask(), 1000*60*5);
This kind of timers can also be canceled with cancel() method
Essentially, after the initial option pane is shown, start a Timer. (A javax.swing one)
You will also need a class-level variable indicating if the temp has been entered yet.
JOptionPane.showMessageDialog(...);
tempHasBeenEntered = false;
Timer tim = new Timer(5 * 60 * 1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!tempHasBeenEntered)
JOptionPane.showMessageDialog("Hey, enter the temp!!");
}
}
tim.setRepeats(false);
tim.start();
You will need to flip the flag once a user enters a temp into the form.
Read the section from the Swing tutorial on How to Use Timers. When the dialog is displayed you start the Timer. When the dialog is closed you stop the Timer.
A Swing Timer should be used, not a TimerTask so that if the Timer fires the code will be executed on the EDT.

Categories