How to add a countdown code to a Java app? - java

I've recently got a project in school.
Create a Java GUI with an image as background and some textbox.
the first textbox is just a text that says: Lunch break at 1pm.
the second textbox is a countdown timer. This timer should appear 5 minutes before the end of the upcoming break, which counts down from 5:00 to 0:00 minutes every second. When reaching 0:00, the timer should respond to a text (e.g. "The
Presentation will start shortly ").
Image as a background: done
Text that says: Lunch break at 1pm: done
Countdown: I'm stuck at this point. I program a countdown timer first on the console. But I really don't know how to include this countdown to a Java GUI.
Do you have any suggestions?
This is my code for the background:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Toolkit;
import javax.swing.JPanel;
import javax.swing.*;
public class Bildhintergrund extends JFrame{
//Background
public Bildhintergrund () {
setTitle(" Bildhintergrund");
setSize(Toolkit.getDefaultToolkit().getScreenSize());
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(new BorderLayout());
setContentPane(new JLabel(new ImageIcon("/path/to/bild.jpg")));
setLayout(new FlowLayout());
JLabel background = new JLabel();
add(background);
//Text
JLabel text = new JLabel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
};
;
JPanel panel = new JPanel();
Dimension size = text.getPreferredSize();
getContentPane().add( text );
text.setFont(text.getFont().deriveFont((float) 58));
text.setText("Lunch break at 1pm");
/*text.setAlignmentX(0);
text.setAlignmentY(0);*/
text.setBounds(300, 300, size.width, size.height);
panel.add(text);
panel.setLayout(null);
add(text);
}
public static void main(String[] args) {
new Bildhintergrund();
}
}
This is my code for the countdown:
{
/*int Time = 5;
String time;
int seconds;
int minutes;*/
int timet= Time * 60; // Convert to seconds
long delay = timet * 1000;
do
{
minutes = timet / 60;
seconds = timet % 60;
time = minutes + ":" + seconds;
System.out.println(GetTimer());
Thread.sleep(1000);
timet = timet - 1;
delay = delay - 1000;
}
while (delay != 0);
System.out.println("Another topic will follow");
}
public static String GetTimer()
{
return time;
}
}

You can use javax.swing.Timer like this example:
javax.swing.Timer timer = new javax.swing.Timer(1000/*timer delay between calling ActionListener.actionPerformed(ActionEvent e) (in milliseconds)*/, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Second over!!!");
//put your code here
}
});
timer.setRepeats(true);//makes timer repeats forever (or until call timer.stop() method)
timer.start();

Related

Getting reaction time after pressing a key game

So I am making a game that records your reaction time after you see something pop up on the screen, but I am having trouble with getting that reaction time. I want the user to press the up arrow key once they see a blue ball and I want to record their reaction time once they pressed that button.
Here is my code:
public class Game extends JPanel
{
private JLabel start, main, time;
private ImageIcon constant, react;
final int width = 600;
final int height = 600;
private Timer replace;
private Random random;
private int randTime;
private long startTime;
private long stopTime;
private long reactionTime;
private Action upAction;
public Game()
{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setPreferredSize(new Dimension(width, height));
setBackground(Color.black);
start = new JLabel("Click Up Arrow when you see a blue ball");
start.setForeground(Color.white);
start.setAlignmentX(Component.CENTER_ALIGNMENT);
add(start);
constant = new ImageIcon("constantCircle.png");
main = new JLabel(constant);
main.setAlignmentX(Component.CENTER_ALIGNMENT);
randomTime();
replace = new Timer(randTime, timeListener);
startTime = System.currentTimeMillis();
replace.setRepeats(false);
replace.start();
add(main);
time = new JLabel("0");
time.getInputMap().put(KeyStroke.getKeyStroke("UP"), "upAction");
time.getActionMap().put("upAction", upAction);
add(time);
}
public void randomTime()
{
random = new Random();
int max = 8000;
randTime = random.nextInt(max);
}
ActionListener timeListener = new ActionListener()
{
public void actionPerformed (ActionEvent e)
{
react = new ImageIcon("reactCircle.png");
main.setIcon(react);
}
};
public class UpAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
stopTime = System.currentTimeMillis();
reactionTime = stopTime - startTime;
time.setText("" + reactionTime);
}
}
}
I setup a "startTime" using System.currentTimeMillis to get the time after the ball turns blue but I am not sure if that is the correct way to do it.
I also setup a "stopTime" in the "UpAction" class where I want to get the time once the user presses up arrow but I it does not work.
if anything doesn't make sense or isn't clear enough, I'll try my best to elaborate more
I came up with the following GUI.
There are two important principles I want to explain. The first is that creating the GUI is a separate process from updating the GUI. The second is that the game process is a state machine. The game is in six separate states. Here's what I wrote to keep the states in mind.
Sequence of events
Left-click button
Wait 2 - 4 seconds to display the circle.
Capture start time
Left-click button
Capture end time.
Calculate and display reaction time.
Repeat 1 - 6.
So, for the GUI, I created a JFrame and three JPanels; an upper JPanel, a drawing JPanel, and a button JPanel.
I started the Swing application with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
The JFrame has a default BorderLayout, which I used to place the three JPanels. The JFrame method calls must be executed in a specific order. This is the order I use for all my Swing applications.
The upper JPanel contains the instructions and the reaction time display. A JTextArea is great for displaying instructions. I put the JTextArea inside an inner JPanel using a FlowLayout, which I placed in the upper JPanel using a BorderLayout. Nesting layouts like this is a good way to organize the Swing components in a logical manner.
I put the reaction time Swing components in another inner JPanel, which I placed in the upper JPanel.
I created a drawing JPanel so I wouldn't have to bother with an image.
The button JPanel holds the Submit JButton.
I created two controller classes. One controller class, ButtonListener, responds to the JButton left-clicks. The other controller class, TimerListener, creates the delay for drawing the circle.
The ButtonListener state variable allows me to provide different functionality with the same ActionListener. If you wish, you can write separate ActionListener classes, one for each function.
By separating my code into view and controller classes, I could separate my concerns and focus on one part of the application at a time.
Here's the complete runnable code. I made all the classes inner classes so I could post this code as one block.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ReactionTimeGame implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new ReactionTimeGame());
}
private long reactionTime;
private DrawingPanel drawingPanel;
private JTextField reactionTimeField;
public ReactionTimeGame() {
this.reactionTime = 0L;
}
#Override
public void run() {
JFrame frame = new JFrame("Reaction Time Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createUpperPanel(), BorderLayout.BEFORE_FIRST_LINE);
this.drawingPanel = new DrawingPanel();
frame.add(drawingPanel, BorderLayout.CENTER);
frame.add(createButtonPanel(), BorderLayout.AFTER_LAST_LINE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createUpperPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel innerPanel = new JPanel(new FlowLayout());
String instructions = "This game will test your reaction time. To play "
+ "the game, left-click on the Submit button. After a random time "
+ "from 2 - 4 seconds, a circle will appear. Left-click the "
+ "Submit button again. Your reaction time will be displayed "
+ "above where the circle was.\n\n"
+ "Left-click the Submit button to start each round of the game.";
JTextArea textArea = new JTextArea(7, 40);
textArea.setEditable(false);
textArea.setText(instructions);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
innerPanel.add(textArea);
panel.add(innerPanel, BorderLayout.BEFORE_FIRST_LINE);
innerPanel = new JPanel(new FlowLayout());
JLabel label = new JLabel("Reaction Time:");
innerPanel.add(label);
reactionTimeField = new JTextField(5);
reactionTimeField.setEditable(false);
updateReactionTime();
innerPanel.add(reactionTimeField);
label = new JLabel("seconds");
innerPanel.add(label);
panel.add(innerPanel, BorderLayout.AFTER_LAST_LINE);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton button = new JButton("Submit");
button.addActionListener(new ButtonListener());
panel.add(button);
return panel;
}
public void setReactionTime(long reactionTime) {
this.reactionTime = reactionTime;
}
public void drawCircle() {
drawingPanel.setDrawCircle(true);
drawingPanel.repaint();
}
public void eraseCircle() {
drawingPanel.setDrawCircle(false);
drawingPanel.repaint();
}
public void updateReactionTime() {
double time = 0.001 * reactionTime;
reactionTimeField.setText(String.format("%.3f", time));
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private boolean drawCircle;
public DrawingPanel() {
this.drawCircle = false;
this.setPreferredSize(new Dimension(300, 300));
}
public void setDrawCircle(boolean drawCircle) {
this.drawCircle = drawCircle;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (drawCircle) {
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
int radius = Math.min(getWidth(), getHeight()) * 9 / 20;
int diameter = radius + radius;
g.setColor(Color.MAGENTA);
g.fillOval(centerX - radius, centerY - radius, diameter, diameter);
}
}
}
public class ButtonListener implements ActionListener {
private int state;
private long startTime;
private final Random random;
private Timer timer;
public ButtonListener() {
this.state = 1;
this.random = new Random();
}
#Override
public void actionPerformed(ActionEvent event) {
switch (state) {
case 1:
int delay = random.nextInt(2000) + 2000;
timer = new Timer(delay, new TimerListener(this));
timer.start();
state = 2;
break;
case 2:
setEndTime(System.currentTimeMillis());
eraseCircle();
state = 1;
break;
}
}
public int getState() {
return state;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public void setEndTime(long endTime) {
long elapsedTime = endTime - startTime;
setReactionTime(elapsedTime);
updateReactionTime();
}
}
public class TimerListener implements ActionListener {
private final ButtonListener listener;
public TimerListener(ButtonListener listener) {
this.listener = listener;
}
#Override
public void actionPerformed(ActionEvent event) {
Timer timer = (Timer) event.getSource();
timer.stop();
if (listener.getState() == 2) {
listener.setStartTime(System.currentTimeMillis());
drawCircle();
}
}
}
}

Java stopwatch GUI program complies but does not run

I have an assignment where I have to create a GUI stopwatch program that has a start, stop, and reset button to the timer.
So far I have a program that compiles correctly but produces the error below when I go to run the program so I'm unsure of how to correct this.
at java.awt.Container.checkNotAWindow(Container.java:492)
at java.awt.Container.addImpl(Container.java:1093)
at java.awt.Container.add(Container.java:419)
at TimerFrame.main(TimerFrame.java:30)
Process completed.
Any help with running my program, or any other improvements that could be made to make the program run more smoothly that would be greatly appreciated. I'm new to learning java so any help is appreciated.
I've included my code down below as well.
Thanks in advance!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TimerFrame {
public static void main(String[] args){
new TimerPanel();
JFrame frame = new JFrame("Stopwatch GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TimerPanel panel = new TimerPanel();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class TimerPanel extends JFrame implements ActionListener {
private int count;
private JButton start;
private JButton stop;
private JButton reset;
private JLabel label;
private Timer timer;
private double time;
private double extra = 0;
public TimerPanel(){
setLayout(new GridLayout(2, 3));
label = new JLabel("00.00", JLabel.CENTER);
add(label);
// Creating a panel (JPanel) for hte buttons to reside in
JPanel buttons = new JPanel();
// initilizing buttons
start = new JButton("Start");
stop = new JButton("Stop");
reset = new JButton("Reset");
// adds the buttons start, stop, and reset to the panel
buttons.add(start);
buttons.add(stop);
buttons.add(reset);
// adds the panel to the frame
add(buttons);
// adding action listeners to the buttons
start.addActionListener(this);
stop.addActionListener(this);
reset.addActionListener(this);
// initilize timer
timer = new Timer(0, this);
timer.setDelay(1000);
setBackground(Color.pink);
setPreferredSize(new Dimension(500, 300));
}
public void actionPerformed(ActionEvent event){
//find the source of the action
if(event.getSource().equals(timer)){
// records the current time event from timer
double currentTime = System.currentTimeMillis();
// finds the elapsed time from time and currentTime
double elapsed = (double) ( currentTime - time) / 1000;
//adds the extra to the elapsed time
elapsed = elapsed + extra;
//displays time in JLabel label
label.setText(String.format("%.1f", elapsed));
} else if (event.getSource().equals(start)){
// the start button has been clicked
if(!timer.isRunning()){
time = System.currentTimeMillis();
timer.start();
}
} else if (event.getSource().equals(stop)) {
// the stop button has been clicked
if(timer.isRunning()){
//record current time in currentTime
double currentTime = System.currentTimeMillis();
// finds the elapsed time from time and currentTime
double elapsed = (double) ( currentTime - time ) / 1000;
// (double) -> casts whatever is produced to be a double
//adds the extra to the elapsed time
elapsed = elapsed + extra;
//stop the timer
timer.stop();
}
} else{
// the reset button has been clicked
// stops the timer before resetting it
if(timer.isRunning()){
timer.stop();
}
// resets the timer
time = System.currentTimeMillis();
extra = 0;
label.setText("00.00");
}
}
}
public class TimerPanel extends JFrame implements ActionListener {
Well, you call your class TimerPanel yet your extend a JFrame.
If the class is a "panel" then it should extend JPanel.
TimerPanel panel = new TimerPanel();
frame.getContentPane().add(panel);
You get the error because you can't add a JFrame to a JFrame.
Any help with running my program, or any other improvements
Why are you trying to write the entire class before doing testing? Testing should be done step by step.
So you start by creating a frame and test that.
Then you add some components to the frame and test if the layout is correct.
Then you add ActionListeners to your buttons (one at a time) and test them.
That way when you have problems you know what you just changed.

Why does my Java timer program not work on Mac?

Is there any reasons due to using java on Mac that my code below wouldn't work? It is working on Windows. However it will not display the GUI on a Mac, I have tried updating java and restarting the machine. It still doesn't display the GUI with the timer.Is it possible it could be the program (Eclipse) that i am using to code in?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TimerApplication extends JFrame implements ActionListener{
private javax.swing.Timer timer;
private JTextField seconds;
private JTextField minutes;
private int nTimeDelay = 50;
private int ticks = 0;
public static void main(String[] args) {
TimerApplication frame = new TimerApplication();
frame.setSize(300, 100);
frame.createGUI();
frame.setVisible(true);
}
private void createGUI(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container window = getContentPane();
window.setLayout(new FlowLayout());;
seconds = new JTextField();
minutes = new JTextField();
window.add(minutes);
window.add(seconds);
timer = new javax.swing.Timer(50, this);
timer.start();
ticks=0;
}
#Override
public void actionPerformed(ActionEvent event) {
if(event.getSource()==timer)
{
minutes.setText(String.format("%02d", (ticks*(nTimeDelay)/1000) / 60));
seconds.setText(String.format("%02d",(ticks*(nTimeDelay)/1000) % 60));
ticks++;
}
}
}
This smells like a multi-threading bug.
I think that there is inadequate synchronization between the "main" thread which initializes the TimerApplication and assigns a value to timer, and the Swing event dispatcher thread (EDT) that will be executing the calls to tour actionPerformed method. This means that it is possible for the actionPerformed call to never see the value that was assigned to timer in the other thread.
Net result: event.getSource() == timer would always be false.
One way to correct this would be make the following changes:
synchronized (this) {
timer = new javax.swing.Timer(50, this);
timer.start();
ticks = 0;
}
and
synchronized (this) {
if (event.getSource() == timer) {
minutes.setText(String.format("%02d", ticks * nTimeDelay / 1000 / 60));
seconds.setText(String.format("%02d", ticks * nTimeDelay / 1000 % 60));
ticks++;
}
}

How and where to use javax.swing Timer

Please help, I'm trying to use javax.swing.Timer in my program. I have looked at lots of examples, but it still doesn't make sense to me. I am writing a program that has the user guessing the price. What I can't seem to figure out is how to have a timer that counts down from 30 seconds after the "new Game" button is clicked. If the user has not guessed the correct answer, then I want the game to display "You lose", but I also want the timer to stop if they get the correct answer in under 30 seconds and display that time. I believe I'm suppose to use
timer = new Timer(Speed, this);
timer.start();
timer.end();
but, I'm not sure what else I need for the timer or where to place these within my code. Any help would be much appreciated. Below is the code for my program...
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class ClockGame extends JFrame {
//Declare fields for GUI components
private JTextField guessField;
private JButton newGameButton;
private JLabel messageLabel;
private JLabel guessLabel;
private ImageIcon clockImage;
private int countTotal;
private Random rand;
private JLabel title;
private int number;
private Timer timer;
public ClockGame() {
//Build GUI
super ("Clock Game");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set layout
this.setLayout(new BorderLayout());
//Create the main panel
JPanel mainPanel = new JPanel();
//Create components and place them in the panel
rand = new Random();
guessLabel = new JLabel("Guess: ");
guessField = new JTextField(20);
messageLabel = new JLabel(" Click New Game to Begin");
clockImage = new ImageIcon("clock.jpg");
newGameButton = new JButton("New Game");
title = new JLabel("The Clock Game", clockImage, SwingConstants.CENTER);
//Set font for clockGameLabel
title.setFont(new Font("Calibri", Font.BOLD, 24));
//Set messageLabel Color
messageLabel.setOpaque(true);
messageLabel.setBackground(Color.yellow);
newGameButton.addActionListener(new ButtonListener());
guessField.addActionListener(new AnswerListener());
//Add components to the panel
mainPanel.add(guessLabel);
mainPanel.add(guessField);
mainPanel.add(newGameButton);
this.add(title, BorderLayout.NORTH);
this.add(messageLabel, BorderLayout.SOUTH);
//Add the panel to this JFrame
this.add(mainPanel, BorderLayout.CENTER);
//Sizes this JFrame so that it is just big enough to hold the components
this.setSize(340,225);
//Make the JFrame visible on the screen
this.setVisible(true);
}
private class AnswerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//Code to check to see if answer is correct
int sum = number;
int answer = Integer.parseInt(guessField.getText());
Color purple = new Color(153, 153, 253);
countTotal++;
if (sum < answer)
{
messageLabel.setText("Too High");
messageLabel.setBackground(Color.red);
}
else if (sum > answer)
{
messageLabel.setText("Too Low");
messageLabel.setBackground(purple);
}
else
{
messageLabel.setText("Correct! It took you " + countTotal + " tries, in " +
timer + " seconds");
messageLabel.setBackground(Color.yellow);
}
}
}
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
number = rand.nextInt(1001);
messageLabel.setText(" The price is between $1 and $1000, begin.");
messageLabel.setBackground(Color.green);
countTotal = 0;
}
}
public static void main(String[] args) {
ClockGame frame = new ClockGame();
}
}
timer.end();
There is no end() method. First you need to read the API for the appropriate method to use.
counts down from 30 seconds after the "new Game" button is clicked.
So in the ActionListener you add to the button you need to start the Timer and schedule it to fire every second. When the Timer fires you decrement your count by 1.
I also want the timer to stop if they get the correct answer
So when they get the correct answer you stop the Timer. So in your code where you update the text of the label you stop the Timer.
If the user has not guessed the correct answer, then I want the game to display "You lose",
So when the timer count reaches 0, you 1) stop the timer and 2) display the message.
In the constructor of you class you would actually create the Timer, so that the above methods in your class have a reference to the Timer so it can be started and stopped as required.
What you really need to do is forget about your game and learn how to use a Timer. So you create a frame with a label and two buttons. The label will display the initial count of 30. Then you have a "Start" button that decrements the label by 1 each time the Timer fires. Then you have a "Stop" button that stops the Timer so the count is not decremented.
Once you understand the basic concept of starting and stopping the Timer, then you add the code to your real program.
Well to begin... you would need a JLabel that is assigned to print "You lose" and another one that prints the Time that it took the player to answer the question. Add these to your Frame however you want.
JLabel outcome = new JLabel(); //setText to win or lose.
JLabel countdown = new JLabel(); //setTime as Timer counts down.
After you have instantiated these Labels. The Timer needs to be instantiated.
Timer timer = new Timer(1000, new ActionListener() { //Change parameters to your needs.
int count = 30;
public void actionPerformed(ActionEvent e) {
count--;
if(count == 0) //They lose
{
countdown.setText("CountDown: " + count);
outcome.setText("You Lose");
timer.stop(); //ends the countdown.
}
else if(userGotAnswer) // You need to create a boolean value that changes when a user gets the answer right.
{
countdown.setText("CountDown: " + count);
outcome.setText("You win");
timer.stop(); //ends the countdown
}
else
{
countdown.setText("CountDown: " + count); //default
}
}
});
Then call
timer.start();
when you want the timer to start.

javax.swing.timer subtracts as much as I click on start button

First of all hi! This is my first post on stackoverflow! This is my second attempt to program something in Java and the first ever attempt with a gui.
I'm actually having 2 problems. The first being the program and the second understanding a part of the code.
How the program should work:
When pressing start it counts down from 01:00 to 00:00 every minute (01:00 -> 00:59 -> 00:58). When you press stop, it stops counting down (duh) and when you press start again, it starts from 01:00 like the first time.
The program problem:
With that said. This only works the first time I press start. When I press start multiple times it subtracts that amount of times from the clock. Pressed 2 times (01:00 -> 00:58 -> 00:56). Pressed 4 times (01:00 -> 00:56 -> 00:52). etc... This obviously should not be happening.
The understanding problem:
I am having a hard time understanding why the timer requires an ActionListener and why it works when you use 'null'. In some cases it also works when using 'this' (which I also don't understand.).
Java Swing Timer Documentation
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CountdownClock extends JFrame
{
private int oneSecond = 1000; //Milliseconds
private Timer timer = new Timer(oneSecond * 60, null);
private int timerCount = 59;
public static void main(String args[])
{
new CountdownClock();
}
CountdownClock()
{
this.getContentPane().setLayout(null);
this.setBounds(800, 450, 300, 125);
final JLabel countdownLabel = new JLabel("01:00");
countdownLabel.setBounds(110, 10, 125, 30);
countdownLabel.setFont(new Font("Serif", Font.PLAIN, 30));
JButton startButton = new JButton("Start");
startButton.setBounds(10, 50, 125, 30);
startButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
timer.setRepeats(true);
timer.stop();
countdownLabel.setText("01:00");
timerCount = 59;
timer.start();
timer.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
if (timerCount == 0)
{
timer.stop();
countdownLabel.setText("00:00");
timerCount = 59;
}
else if (timerCount <= 9)
{
countdownLabel.setText("00:0" + String.valueOf(timerCount));
timerCount = timerCount - 1;
}
else
{
countdownLabel.setText("00:" + String.valueOf(timerCount));
timerCount = timerCount - 1;
}
}
});
}
});
JButton stopButton = new JButton("Stop");
stopButton.setBounds(150, 50, 125, 30);
stopButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
timer.stop();
countdownLabel.setText("01:00");
timerCount = 59;
}
});
add(countdownLabel);
add(startButton);
add(stopButton);
setVisible(true);
}
}
This happens because you are adding an ActionListener to the Timer every time that you press the button. So, since a Timer allows multiple listeners, everyone of them gets notified when the timer ticks.
To solve the problems you could just instantiate a new Timer every time you press the start button (timer = new Timer()). Or add the ActionListener just once in your JFrame constructor . Or even remove the listener (but you should save a reference to it somewhere).

Categories

Resources