I have a GUI with a form for people to fill up and I would like to put a countdown timer at the top right hand corner of the page
Heres the method for the timer to get the remaining time. Say my form class is FillForm and the timer method is found in Timer.
How do I put a dynamic (constantly updating) timer inside of the GUI?
public String getRemainingTime() {
int hours = (int)((this.remainingTime/3600000) % 60);
int minutes = (int)((this.remainingTime/60000) % 60);
int seconds = (int)(((this.remainingTime)/1000) % 60);
return(format.format(hours) + ":" + format.format(minutes)+
":" + format.format(seconds));
}
GUI is built using NetBeans GUI builder.
Try This :
import javax.swing.Timer;
Timer timer=new Timer(1000,new ActionListener(){
public void actionPerformed(ActionEvent e)
{
//code here
}
});
timer.start();
//timer.stop()
Every one Seconds Timer Execute.
Try This Demo :
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
class Counter {
private static int cnt;
static JFrame f;
public static void main(String args[]) {
f=new JFrame();
f.setSize(100,100);
f.setVisible(true);
ActionListener actListner = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
cnt += 1;
if(cnt%2==0)
{
f.setVisible(true);
}
else
{
f.setVisible(false);
}
}
};
Timer timer = new Timer(500, actListner);
timer.start();
}
}
You should abstract your timer into a UI component. JLabel seems the most suited as it is a text that you want to display.
public class TimerLabel extends JLabel {
// Add in your code for 'format' and 'remainingTime'.
// Note that the first time that 'getText' is called, it's called from the constructor
// if the superclass, so your own class is not fully initialized at this point.
// Hence the 'if (format != null)' check
public TimerLabel() {
Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();
}
public String getRemainingTime() {
int hours = (int) ((this.remainingTime / 3600000) % 60);
int minutes = (int) ((this.remainingTime / 60000) % 60);
int seconds = (int) (((this.remainingTime) / 1000) % 60);
return (format.format(hours) + ":" + format.format(minutes) + ":" + format.format(seconds));
}
#Override
public String getText() {
if (format != null) {
return getRemainingTime();
} else {
return "";
}
}
"Could i add this into a Swing.JPanel or something?"
Just put it in the constructor of your form class. Declare the Timer timer; as a class member and not locally scoped so that you can use the start() method like in a button's actionPerformed. Something like
import javax.swing.Timer;
public class GUI extends JFrame {
public Timer timer = null;
public GUI() {
timer = new Timer (500, new ActionListener(){
public void actionPerformed(ActionEvent e) {
if (timerGetsToZero) {
((Timer)e.getSource()).stop();
} else {
timeLabel.setText(getRemainingTime());
}
}
});
}
private void startButtonActionPerformed(ActionEvent e) {
timer.start();
}
}
Related
I'm trying to make a timer that will count up from 00h:00m:00s, with the ability to pause and restart the count from its current time.
Heres the solution I currently have: It will always restart the timer from 0 instead of continuing where it left off. Also, for another inexplicable reason, the hours always display as 07 instead of 00. Does anyone know how I could fix these issues, to have it start counting up from its previous value, and display the correct amount of hours elapsed?
private final SimpleDateFormat date = new SimpleDateFormat("KK:mm:ss");
private long startTime = 0;
private final ClockListener clock = new ClockListener();
private final Timer normalTimer = new Timer(53, clock);
startTimerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(startTime == 0) {
startTime = System.currentTimeMillis();
}
else {
startTime += (System.currentTimeMillis() - startTime);
}
normalTimer.start();
}
});
stopTimerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
normalTimer.stop();
}
});
private void updateClock(){
Date elapsed = new Date(System.currentTimeMillis() - startTime);
timerText.setText(date.format(elapsed));
}
private class ClockListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
updateClock();
}
}
Introduction
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section.
Your code wasn't runnable, so I created the following GUI.
When you press the "Start" button, the timer starts counting. 37 seconds.
2 minutes, 7 seconds.
1 hour, 6 minutes, 11 seconds.
Pressing the "Pause button pauses the count. Pressing the "Restart" button resumes the count. You can pause and resume the count as many times as you want.
Pressing the "Stop" button stops the counter. You can press the "Reset" button to reset the counter before starting again.
Explanation
When creating a Swing application, using the model-view-controller (MVC) pattern helps to separate your concerns and allows you to focus on one part of the application at a time.
Creating the application model made creating the GUI much easier. The application model is made up of one or more plain Java getter/setter classes.
The CountupTimerModel class keeps long fields to hold the duration in milliseconds and the previous duration. This way, I don't have to pause and restart the Swing Timer.
The duration is the difference between the current time and the start time. I use the System.currentTimeMillis() method to calculate the duration.
The GUI is fairly straightforward.
I made the JButton ActionListeners lambdas. I made the TimerListener a separate class to move the code out of that particular lambda.
Code
Here's the complete runnable code. I made the additional classes inner classes so I could post the code as one block.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class CountupTimerGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new CountupTimerGUI());
}
private final CountupTimerModel model;
private JButton resetButton, pauseButton, stopButton;
private JLabel timerLabel;
public CountupTimerGUI() {
this.model = new CountupTimerModel();
}
#Override
public void run() {
JFrame frame = new JFrame("Countup Timer GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createDisplayPanel(), BorderLayout.NORTH);
frame.add(createButtonPanel(), BorderLayout.SOUTH);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createDisplayPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
Font font = panel.getFont().deriveFont(Font.BOLD, 48f);
timerLabel = new JLabel(model.getFormattedDuration());
timerLabel.setFont(font);
panel.add(timerLabel);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
Font font = panel.getFont().deriveFont(Font.PLAIN, 16f);
resetButton = new JButton("Reset");
resetButton.setFont(font);
panel.add(resetButton);
resetButton.addActionListener(event -> {
model.resetDuration();
timerLabel.setText(model.getFormattedDuration());
});
pauseButton = new JButton("Restart");
pauseButton.setFont(font);
panel.add(pauseButton);
pauseButton.addActionListener(event -> {
String text = pauseButton.getText();
if (text.equals("Pause")) {
model.pauseTimer();
pauseButton.setText("Restart");
} else {
model.startTimer();
pauseButton.setText("Pause");
}
});
Timer timer = new Timer(200,
new CountupListener(CountupTimerGUI.this, model));
stopButton = new JButton("Start");
stopButton.setFont(font);
panel.add(stopButton);
stopButton.addActionListener(event -> {
String text = stopButton.getText();
if (text.equals("Start")) {
model.resetDuration();
model.startTimer();
timer.start();
resetButton.setEnabled(false);
stopButton.setText("Stop");
} else {
model.stopTimer();
timer.stop();
resetButton.setEnabled(true);
stopButton.setText("Start");
}
});
Dimension d = getLargestJButton(resetButton, pauseButton, stopButton);
resetButton.setPreferredSize(d);
pauseButton.setPreferredSize(d);
stopButton.setPreferredSize(d);
pauseButton.setText("Pause");
return panel;
}
private Dimension getLargestJButton(JButton... buttons) {
Dimension largestDimension = new Dimension(0, 0);
for (JButton button : buttons) {
Dimension d = button.getPreferredSize();
largestDimension.width = Math.max(largestDimension.width, d.width);
largestDimension.height = Math.max(largestDimension.height,
d.height);
}
largestDimension.width += 10;
return largestDimension;
}
public JButton getResetButton() {
return resetButton;
}
public JButton getPauseButton() {
return pauseButton;
}
public JButton getStopButton() {
return stopButton;
}
public JLabel getTimerLabel() {
return timerLabel;
}
public class CountupListener implements ActionListener {
private final CountupTimerGUI view;
private final CountupTimerModel model;
public CountupListener(CountupTimerGUI view, CountupTimerModel model) {
this.view = view;
this.model = model;
}
#Override
public void actionPerformed(ActionEvent event) {
model.setDuration();
view.getTimerLabel().setText(model.getFormattedDuration());
}
}
public class CountupTimerModel {
private boolean isRunning;
private long duration, previousDuration, startTime;
public CountupTimerModel() {
resetDuration();
}
public void resetDuration() {
this.duration = 0L;
this.previousDuration = 0L;
this.isRunning = true;
}
public void startTimer() {
this.startTime = System.currentTimeMillis();
this.isRunning = true;
}
public void pauseTimer() {
setDuration();
this.previousDuration = duration;
this.isRunning = false;
}
public void stopTimer() {
setDuration();
this.isRunning = false;
}
public void setDuration() {
if (isRunning) {
this.duration = System.currentTimeMillis() - startTime
+ previousDuration;
}
}
public String getFormattedDuration() {
int seconds = (int) ((duration + 500L) / 1000L);
int minutes = seconds / 60;
int hours = minutes / 60;
StringBuilder builder = new StringBuilder();
if (hours > 0) {
builder.append(hours);
builder.append(":");
}
minutes %= 60;
if (hours > 0) {
builder.append(String.format("%02d", minutes));
builder.append(":");
} else if (minutes > 0) {
builder.append(minutes);
builder.append(":");
}
seconds %= 60;
if (hours > 0 || minutes > 0) {
builder.append(String.format("%02d", seconds));
} else {
builder.append(seconds);
}
return builder.toString();
}
}
}
So I'm trying to make a reaction game where you press start button, a hidden timer that will countdown to zero from a random number between 1 & 10 seconds. Most answer regarding java timers recommend using
Thread.sleep(1000);
However this interrupts the entire program while I just wants it to countdown. How should I solve this?
After pressing start and the program has counted down from a random number. The blue icon (entire code below) will turn red and then you're supposed to press it and it will display the time it took for you to press it.
Code is focus:
public void countDown() throws InterruptedException {
int random = r.nextInt((10000 - 1000) + 1) + 1000;
while(random >= 0){
Thread.sleep(1000);
random -= 1000;
}
if (random <= 0) {
button_1.setIcon(img_react);
repaint();
}
}
Image files used:
http://imgur.com/DjI8Udr
http://imgur.com/XKQW6DI
Entire code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
import java.util.*;
public class Interface extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
ImageIcon img_idle = new ImageIcon("img_idle.png");
ImageIcon img_react = new ImageIcon("img_react.png");
JButton button_1 = new JButton(img_idle);
JButton start = new JButton("Start");
Random r = new Random();
public Interface() {
super("Simple Reaction Game");
setSize(180, 350);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
Container contentArea = getContentPane();
contentArea.setBackground(Color.white);
FlowLayout flowManager = new FlowLayout();
contentArea.setLayout(flowManager);
button_1.addActionListener(this);
start.addActionListener(this);
contentArea.add(button_1);
contentArea.add(start);
setContentPane(contentArea);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == start) {
try {
countDown();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
public void countDown() throws InterruptedException {
Thread t = new Thread();
int random = r.nextInt((10000 - 1000) + 1) + 1000;
while(random >= 0){
t.sleep(1000);
random -= 1000;
}
if (random <= 0) {
button_1.setIcon(img_react);
repaint();
}
}
public static void main(String args[]) {
new Interface();
}
}
You can't just use Thread.sleep(), it won't work as you think it does. Instead, you can use javax.swing.Timer which is made to do what you're trying to do.
Some notes from the docs (if you didn't bother reading it):
Timers perform their waiting using a single, shared thread.
Timers can safely perform operations on Swing components.
Timers can safely perform operations on Swing components.
The javax.swing.Timer has two features that can make it a little easier to use with GUIs.
I've modified an example from here to show how you can adapt it to your needs. It's using your random generated number which is generated each time the timer is finished and you press "start".
import java.awt.*;
import java.awt.event.*;
import java.text.SimpleDateFormat;
import javax.swing.*;
import javax.swing.UnsupportedLookAndFeelException;
import java.util.Random;
public class Interface {
public static void main(String[] args) {
new Interface();
}
public Interface() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Timer timer;
private long startTime = -1;
private long duration;
private JLabel label;
private JButton start;
public TestPane() {
start = new JButton("Start");
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
timer = new Timer(10, 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;
timer.stop();
}
SimpleDateFormat df = new SimpleDateFormat("mm:ss:SSS");
label.setText(df.format(duration - clockTime));
}
});
timer.setInitialDelay(0);
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!timer.isRunning()) {
duration = new Random().nextInt((10000 - 1000) + 1) + 1000;
startTime = -1;
timer.start();
}
}
});
label = new JLabel("...");
add(label);
add(start);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 250);
}
}
}
I would suggest a different architecture. Why do you think you need to "count down" anything?!
Meaning: all you care about is that you want to do "something" after a random period of time; so something like this (using pseudo-code) might be easier in the end:
now = ... get current time
then = now + random value
schedule the Swing timer to sent some Event X "then"
And simply have some code that that reacts to incoming X events.
I am trying to make a rubix cube timer for my friend. To start the timer you hold down space bar, and once you let go it starts. I am having a problem though, when I hold down the space bar the timer starts at whatever time it is. I want to be able to reset it to 0 but whenever I try to do that everything glitches out. Could anyone tell me how to fix it, or how to do this in a more efficient way? Thanks!
package dev.suns.rubix_timer;
import java.awt.Color;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Timer;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class RubixTimerMain extends JFrame {
private JPanel contentPane;
private JLabel labelTimer;
private Timer timer;
public RubixTimerMain() {
createWindow();
}
public static void main(String[] args) {
new RubixTimerMain();
}
private void createWindow() {
// setUndecorated(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(Toolkit.getDefaultToolkit().getScreenSize());
setLocationRelativeTo(null);
setExtendedState(JFrame.MAXIMIZED_BOTH);
contentPane = new JPanel();
contentPane.setBackground(new Color(201, 77, 83));
contentPane.setLayout(null);
setContentPane(contentPane);
addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
startTimer();
}
}
});
JLabel lblMinimize = new JLabel("-");
lblMinimize.setBounds(1835, -20, 16, 95);
lblMinimize.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
setState(JFrame.ICONIFIED);
}
#Override
public void mouseEntered(MouseEvent e) {
lblMinimize.setForeground(Color.BLACK);
}
#Override
public void mouseExited(MouseEvent e) {
lblMinimize.setForeground(Color.WHITE);
}
});
lblMinimize.setForeground(Color.WHITE);
lblMinimize.setFont(new Font("Segoe UI", Font.PLAIN, 40));
contentPane.add(lblMinimize);
JLabel lblX = new JLabel("X");
lblX.setBounds(1873, 0, 24, 54);
lblX.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
System.exit(0);
}
#Override
public void mouseEntered(MouseEvent e) {
lblX.setForeground(Color.BLACK);
}
#Override
public void mouseExited(MouseEvent e) {
lblX.setForeground(Color.WHITE);
}
});
lblX.setFont(new Font("Segoe UI", Font.PLAIN, 40));
lblX.setHorizontalAlignment(SwingConstants.CENTER);
lblX.setForeground(Color.WHITE);
contentPane.add(lblX);
labelTimer = new JLabel("0.0.0");
labelTimer.setHorizontalAlignment(SwingConstants.CENTER);
labelTimer.setFont(new Font("DINPro-Bold", Font.PLAIN, 200));
labelTimer.setForeground(Color.WHITE);
labelTimer.setBounds(371, 134, 1418, 653);
contentPane.add(labelTimer);
setVisible(true);
}
This is where I have the timer code. I have tried to reset cal to 0 in several different places but it is not working.
private void startTimer() {
new Thread()
{
public void run()
{
while(true)
{
Calendar cal = new GregorianCalendar();
int minutes = cal.get(Calendar.MINUTE);
int seconds = cal.get(Calendar.SECOND);
int milliseconds = cal.get(Calendar.MILLISECOND);
labelTimer.setText(minutes + "." + seconds + "." + milliseconds);
}
}
}.start();
}
}
In order to be able to stop the timer thread you need to have some means of communicating between the main thread and the timer thread. A synchronized member variable of the RubixTimerMain class can do that:
private Boolean isStopped = new Boolean(true);
Then you can add two methods. One stops the timer by setting the variable, the other one checks the current state of the variable.
private void stopTimer(){
synchronized(isStopped){
isStopped = true;
}
}
private boolean isTimerRunning(){
boolean result = false;
synchronized(isStopped){
result = !isStopped;
}
return result;
}
You will want to change the listener event of the space key (in createWindow) like this so that it starts and stops the timing:
addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
if (isTimerRunning()){
stopTimer();
} else {
startTimer();
}
}
}
});
Finally you need to adapt your thread function so that it only runs if the stopped state variable is false. Notice that it uses the isTimerRunning method instead of directly accessing the variable. Also the error of displaying the wrong time is fixed by converting the value of the GregorianCalendar into milliseconds first, then subtracting the recorded start time from the current time.
private void startTimer() {
new Thread()
{
public void run()
{
long timeStart = new GregorianCalendar().getTimeInMillis();
synchronized(isStopped){
isStopped = false;
}
while(isTimerRunning())
{
long timeNow = new GregorianCalendar().getTimeInMillis() - timeStart;
long milliseconds = (timeNow % 1000);
timeNow = (long) Math.floor(timeNow * 0.001f);
long seconds = (timeNow % 60);
timeNow = (long)Math.floor((float)timeNow / 60f);
long minutes = timeNow;
labelTimer.setText(minutes + "." + seconds + "." + milliseconds);
}
}
}.start();
}
One problem may be that you're not interacting with labelTimer on the EDT (Event Dispatch Thread).
In Swing, all interactions with UI objects must happen on this thread.
What happens if you make sure your call to setText happens within an invocation of SwingUtilities#invokeLater: https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable)
I want to display in my JPanel a JLabel with timer in this mode, for example:
03:50 sec
03:49 sec
....
....
00:00 sec
So I have build this code:
#SuppressWarnings("serial")
class TimeRefreshRace extends JLabel implements Runnable {
private boolean isAlive = false;
public void start() {
Thread t = new Thread(this);
isAlive = true;
t.start();
}
public void run() {
int timeInSecond = 185
int minutes = timeInSecond/60;
while (isAlive) {
try {
//TODO
} catch (InterruptedException e) {
log.logStackTrace(e);
}
}
}
}//fine autoclass
And with this code, I can start the JLabel
TimeRefreshRace arLabel = new TimeRefreshRace ();
arLabel.start();
So I have the time in secondo for example 180 second, how can I create the timer?
Here is an example, how to build a countdown label. You can use this pattern to create your component.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public class TimerTest {
public static void main(String[] args) {
final JFrame frm = new JFrame("Countdown");
final JLabel countdownLabel = new JLabel("03:00");
final Timer t = new Timer(1000, new ActionListener() {
int time = 180;
#Override
public void actionPerformed(ActionEvent e) {
time--;
countdownLabel.setText(format(time / 60) + ":" + format(time % 60));
if (time == 0) {
final Timer timer = (Timer) e.getSource();
timer.stop();
}
}
});
frm.add(countdownLabel);
t.start();
frm.pack();
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setVisible(true);
}
private static String format(int i) {
String result = String.valueOf(i);
if (result.length() == 1) {
result = "0" + result;
}
return result;
}
}
You could within your try block call the Event Dispatcher Thread (EDT) and update your UI:
try {
SwingUtils.invokeLater(new Runnable() {
#Override
public void run() {
this.setText(minutes + " left");
}
}
//You could optionally block your thread to update your label every second.
}
Optionally, you could use a Timer instead of an actual thread, so your TimerRefreshRace will have its own timer which periodically fires an event. You would then use the same code within your try-catch block to update the UI.
I'm using the swing Timer to make a countdown clock in Netbeans:
public void startTimer() {
System.out.println(right + "value");
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.out.println("action");
timerLabel.setText("" + seconds);
--seconds;
System.out.println(seconds);
if (seconds == -1 && seconds < 0) {
System.out.print("zero");
//displayTimer.stop();
wrong();
dispose();
}
}
};
displayTimer = new Timer(1000, listener);
displayTimer.setInitialDelay(100);
displayTimer.start();
if (right == null) {
System.out.println("null");
} else if (right == true) {
System.out.println("truehere");
displayTimer.stop();
right = null;
seconds = 20;
displayTimer.setDelay(10000);
displayTimer.setInitialDelay(100);
displayTimer.start();
} else if (right == false) {
System.out.print("wrong");
//displayTimer.stop();
seconds = 20;
}
}
I just use System.out.print to test the program, it's not a part of the real program.
I call the stop() method but the timer continues to count. Also, I create a new timer by displayTimer = new javax.swing.Timer(10000, listener); but it counts twice as fast. Can anyone help?
EDIT:
Here is my timer (sort of SSCCE):
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Scanner;
import javax.swing.*;
public class JavaApplication8 {
public static void startTimer() {
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
int seconds = 20;
seconds--;
System.out.println(seconds);
if (seconds == -1 && seconds < 0) {
System.out.print("zero");
}
}
};
Timer displayTimer = new Timer(1000, listener);
displayTimer.setInitialDelay(100);
displayTimer.start();
}
public static void main(String[] args) {
System.out.println("Type win to win!");
startTimer();
String read;
Boolean right;
int seconds;
Scanner scanIn = new Scanner(System.in);
read = scanIn.nextLine();
if (read.equals("win")){
right = true;
}
else{
right = false;
}
if (right == true) {
System.out.println("correct");
//displayTimer.stop();
right = null;
seconds = 20;
//displayTimer.setDelay(10000);
//displayTimer.setInitialDelay(100);
//displayTimer.start();
} else if (right == false) {
System.out.print("incorrect");
//displayTimer.stop();
seconds = 20;
right = null;
}
}
}
it doesn't work right in that the seconds don't show up, but it does show 20 times which is what I want. This is just in its own application, in my real program it is easier to see the problem.
I've noticed that the first time the game runs it works fine. Then I click play again (resets the whole game) and it goes twice as fast. Maybe I'm not resetting something correctly? Here is my reset code:
// Reset Everything
PlayFrame.seconds = 20;
PlayFrame.winnings = 0;
PlayFrame.right = false;
//PlayFrame.displayTimer.stop();
PlayFrame.questionLabel.setText(null);
PlayFrame.count = 0;
WelcomeFrame WFrame = new WelcomeFrame();
WFrame.setVisible(true);
setVisible(false);
PlayFrame P = new PlayFrame();
P.dispose();
if (PlayFrame.seconds == -1 && PlayFrame.seconds < 0){
PlayFrame.displayTimer.stop();
}
}
Its just pseudo code to see how timer can be started and stopped.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.Timer;
public class TimerOnJLabel extends JFrame {
private static final long serialVersionUID = 1L;
long start = System.currentTimeMillis();
long elapsedTimeMillis;
int sec = 5;
Timer timer;
public TimerOnJLabel() {
super("TooltipInSwing");
setSize(400, 300);
getContentPane().setLayout(new FlowLayout());
final JLabel b1;
final JRadioButton jrb = new JRadioButton();
b1 = new JLabel("Simple tooltip 1");
ActionListener timerTask = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
elapsedTimeMillis = System.currentTimeMillis();
b1.setText("Timer : " + (elapsedTimeMillis-start)/1000+" ::::: " +sec);
System.out.println("Timer working: " + sec);
if(--sec == 0){
timer.stop();
System.out.println("Timer Stopped");
}
}
};
timer = new Timer(1000, timerTask);
System.out.println("Timer Started");
timer.start();
getContentPane().add(b1);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
}
public static void main(String args[]){
new TimerOnJLabel();
}
}
I hope this help.