This question already has answers here:
Dynamic Clock in java
(7 answers)
Closed 4 years ago.
I am creating a program that gets the time and displays it in a JFrame (it also updates the background to be the color #[HOUR][MIN][SEC] like on rhysperry.co.nf ). My problem is the timer seams to only update every 2-4 seconds(on lower end machines). I have the code and am wondering how I would go about optimizing an already small program.
Please tolerate bad coding practices as I still don't fully understand Java.
Here is my code - Window.java:
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
public class Window {
/**
* Simple color changing clock based on the website the website rhysperry.co.nf
*
* #author Rhys Perry
*/
public static void main(String[] args) throws IOException, FontFormatException, InterruptedException {
//Import font
InputStream in = Window.class.getResourceAsStream("Lato-Hairline.ttf");
Font font = Font.createFont(Font.TRUETYPE_FONT, in).deriveFont(50f);
//Initialise the Frame, Panel and label
JFrame frame= new JFrame("Hex Clock");
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
JLabel label = new JLabel();
label.setFont(font);
label.setPreferredSize(new Dimension(200, 350));
label.setForeground(Color.WHITE);
//Merge Frame, Panel and "This is a test")Label. Make window visible
panel.add(label);
frame.add(panel);
frame.setSize(700, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//Setup calendar
Calendar calendar;
//Initialise some variables to do with time management
String formattedhour;
String formattedmin;
String formattedsec;
//Main loop to get the time and update the background ad Label
while(true) {
//Get hours, minutes and seconds
calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
if (hour < 10) { formattedhour = "0" + hour; } else { formattedhour = hour + "";}
int min = calendar.get(Calendar.MINUTE);
if (min < 10) { formattedmin = "0" + min; } else { formattedmin = min + "";}
int sec = calendar.get(Calendar.SECOND);
if (sec < 10) { formattedsec = "0" + sec; } else { formattedsec = sec + "";}
//Format and update the necessary components
String time = formattedhour + ":" + formattedmin + " " + formattedsec;
label.setText(time);
String hex = "#" + formattedhour + formattedmin + formattedsec;
panel.setBackground(Color.decode(hex));
panel.repaint();
}
}
}
You can use javax.swing.Timmer instead. It executes a task repeatedly after interval of time. https://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
}
};
Timer timer = new Timer(10 ,taskPerformer);
timer.start();
I am trying to creating countdown timer using java with Netbeans 8.1 IDE,, My problem is when the timer gets 00:00 it do not want to stop..I have trying to write timer.stop(); but it still not working...Maybe you can help me ..
this is my source code :
ActionListener action;
action = new ActionListener() {
public void actionPerformed(ActionEvent e) {
seconds--;
if(seconds==0){
minutes--;
seconds=60;
}
if(seconds==0 && minutes==0){
timer.stop();
}
String min = minutes <= 9? "0"+minutes:minutes+"";
String seg = seconds <= 9? "0"+seconds:seconds+"";
txtRemaining.setText(min+":"+seg);
}
};
this.timer = new Timer(interval, action);
this.timer.start();
Your problem is here:
if(seconds==0 && minutes==0){
timer.stop();
}
seconds can never == 0 here since just before this block of code you call:
if(seconds==0){
minutes--;
seconds=60;
}
and if seconds == 0, you set it immediately to 60. The solution is to swap these two lines:
// call this **first**
if(seconds==0 && minutes==0){
timer.stop();
}
// call this **second**
if(seconds == 0){
minutes--;
seconds = 60;
}
This question already has an answer here:
I don't know how to display timer when stopped
(1 answer)
Closed 6 years ago.
I'm trying to display the current time in a JFrame. How can I refresh the text in the JLabel without opening a separate frame each time it has to update?
Here's all of my code so far...
Test
public class Test{
static String timeDisplay = "";
public static class time extends Thread{
static int timeHours = 7;
static int timeMins = 30;
static int timeSecs = 0;
#Override
public void run(){
while(true){
try{
time.sleep(1000);
timeSecs++;
if(timeSecs == 60){
timeMins++;
timeSecs = 0;
}
if(timeMins == 60){
timeHours++;
timeMins = 0;
}
if(timeHours < 10){
if(timeMins < 10){
if(timeSecs < 10){
timeDisplay = "0" + timeHours + ":" + "0" + timeMins + ":" + "0" + timeSecs;
}
else{
timeDisplay = "0" + timeHours + ":" + "0" + timeMins + ":" + timeSecs;
}
}
else{
if(timeSecs < 10){
timeDisplay = "0" + timeHours + ":" + timeMins + ":" + "0" + timeSecs;
}
else{
timeDisplay = "0" + timeHours + ":" + timeMins + ":" + timeSecs;
}
}
}
else{
if(timeMins < 10){
if(timeSecs < 10){
timeDisplay = timeHours + ":" + "0" + timeMins + ":" + "0" + timeSecs;
}
else{
timeDisplay = timeHours + ":" + "0" + timeMins + ":" + timeSecs;
}
}
else{
if(timeSecs < 10){
timeDisplay = timeHours + ":" + timeMins + ":" + "0" + timeSecs;
}
else{
timeDisplay = timeHours + ":" + timeMins + ":" + timeSecs;
}
}
}
System.out.println(timeDisplay);
//CountDown time = new CountDown(timeDisplay);
}
catch(Exception e){
System.out.println("Something went wrong :(");
}
}
}
}
public static void main(String[] args){
time time = new time();
time.start();
try {
TimeUnit.SECONDS.sleep(1);
CountDown window = new CountDown(timeDisplay);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(500, 500);
window.setVisible(true);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
CountDown
public class CountDown extends JFrame{
private static final long serialVersionUID = 1L;
static JLabel label = new JLabel();
public CountDown(String time){
super("Title");
setLayout(new FlowLayout());
add(label);
label.setText("Current Time: " + time);
Handler eventHandler = new Handler();
}
private class Handler implements ActionListener{
public void actionPerformed(ActionEvent event){
String string = "";
if(event.getSource()==""){
string = String.format("label 1: %s", event.getActionCommand());
}
}
}
}
My intentions for this program was to make a frame that displayed the current time. It's using local time from the program, not the actual time. Thanks in advance, and feel free to let me know if I should change anything in my code to make it better.
You should first create an instance of CountDown and then call one of its method setting the text of the label.
In CountDown you have to call the JLabel.setText. method to set the label's text:
public void displayTime(String time){
label.setText("Current Time: " + time);
}
...and instead of System.out.println(time) call
time.displayTime(timeDisplay);
Instead of using a simple thread , you'd better use a java.util.Timer or even better a javax.swing.Timer that is better suited for gui objects.
Another remark: class names begin by an upper case letter while methods or variables begin by a lower case method.
Finally what has your handler to do here. You don't register it and it seems useless.
The API Docs will be your friend. Take a look at the documentation for JLabel, particularly the method setText(). You can use this method again in your event handler to change the text of your label.
But another problem you have is that you are neither firing nor registering for events, so that actionPerformed function you have written is never being called. If second-accuracy is good enough, you could simplify your code greatly, using javax.swing.Timer. Without changing your code where unnecessary, this should get you on the right path:
public class CountDown extends JFrame{
private static final long serialVersionUID = 1L;
private JLabel label = new JLabel(); // note: understand static keyword before using it.
private long startTime = System.currentTimeMillis(); // gets the current time in milliseconds, when your class is initialized.
public CountDown(String time){
super("Title");
setLayout(new FlowLayout());
add(label);
// label.setText("Current Time: " + time); "time" was never in scope here.
Handler eventHandler = new Handler();
new Timer(1000, eventHandler).start(); // will execute ~1/sec
}
private class Handler implements ActionListener{
public void actionPerformed(ActionEvent event){
// NOTE: here, you could put all of your logic that was previously
// in your Thread to determine the time, then use the result
// with label.setText();
long currentTime = System.currentTimeMillis();
long upTime = currentTime - startTime; // this is how many milliseconds your JFrame has been up and running.
// TODO: formate upTime however you desire.
label.setText( <whatever_you_calculate_directly_above> );
}
}
}
}
You will also need to rewrite your main method to initialized your Frame. That should do it.
public static void main( String[] args){
JFrame frame = new CountDown();
frame.setVisible(true);
}
If your main method is in a separate file, you will need to import CountDown near the beginning of that file.
I'm doing a Java project where I have to make a GUI that contains multiple timers that countdown from a user input time. When I create only one timer, the program works fine, but when I try to include multiple timers, each timer will countdown faster based on how many timers there are. I think the problem is being caused by the ActionListener being called multiple times each time the swing timer calls for an action, but I do not know how to solve that problem.
Here is my CountDownTimer class that contains the attributes and methods for the timer:
package pack1;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
/*******************************************************************************
* Class that contains the methods needed to create a timer that counts down
* #version January 2014, Project 1
********************************************************************************/
public class CountDownTimer {
/** Amount of hours that are being counted down in the timer */
int hours;
/** Amount of minutes that are being counted down in the timer */
int minutes;
/** Amount of seconds that are being counted down in the timer */
int seconds;
/** Boolean that determines if the add method will work. It is changed with the toggleSuspend method */
static boolean toggle = false;
/*****************************************************************************************
* Default constructor that creates a CountDownTimer object with no time contained in it
*****************************************************************************************/
public CountDownTimer() {
hours = 0;
minutes = 0;
seconds = 0;
}
/*********************************************************************************************
* Constructor that uses the input amount of hours, minutes, and seconds to count down from
*
* Does not allow time that is negative or allow seconds or minutes that are over 60
* #param hours amount of hours that will be counted down from
* #param minutes amount of minutes that will be counted down from
* #param seconds amount of seconds that will be counted down from
*********************************************************************************************/
public CountDownTimer(int hours, int minutes, int seconds) {
super();
// doesn't allow negative minutes, seconds, or hours
if (seconds < 0 || minutes < 0 || hours < 0) {
throw new IllegalArgumentException("Time cannot be negative");
}
// doesn't allow seconds that are higher than 60
if (seconds >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 seconds");
}
// doesn't allow minutes that are higher than 60
if (minutes >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 minutes");
}
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
}
/*********************************************************************
* Constructor that takes minutes and seconds, and sets hours to zero
* also doesn't allow minutes or seconds to be negative or above 60
* #param minutes amount of minutes that will be counted down from
* #param seconds amount of seconds that will be counted down from
*************************************************************************/
public CountDownTimer(int minutes, int seconds) {
super();
// doesn't allow seconds minutes or hours to be negative
if (seconds < 0 || minutes < 0 || hours < 0) {
throw new IllegalArgumentException("Time cannot be negative");
}
// doesn't allow seconds to be greater than 60
if (seconds >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 seconds");
}
// doesn't allow minutes to be greater than 60
if (minutes >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 minutes");
}
this.hours = 0;
this.minutes = minutes;
this.seconds = seconds;
}
/***********************************************************************
* Constructor that only takes seconds and sets hours and minutes to 0
* does not allow the seconds to be above 60 or negative
* #param seconds amount of seconds that will be counted down from
*************************************************************************/
public CountDownTimer(int seconds) {
super();
// doesn't allow seconds minutes or hours to be negative
if (seconds < 0 || minutes < 0 || hours < 0) {
throw new IllegalArgumentException("Time cannot be negative");
}
// doesn't allow seconds to be greater than 60
if (seconds >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 seconds");
}
this.hours = 0;
this.minutes = 0;
this.seconds = seconds;
}
/**
* Constructor that clones one CountDownTimer object into a new CountDownTimer object
* #param other The CountDownTimer object that is being cloned
* */
public CountDownTimer(CountDownTimer other) {
this.hours = other.hours;
this.minutes = other.minutes;
this.seconds = other.seconds;
}
/*******************************************************************************************************************************
* Constructor that converts a string in the format of "00:00:00" into seconds minutes and hours so it can be counted down from
* #param startTime String that is converted into seconds minutes and hours
*******************************************************************************************************************************/
public CountDownTimer(String startTime) {
// Separates the seconds minutes and hours into an array
String[] parts = startTime.split(":");
// if the array has only one cell, that means only seconds were input
if (parts.length == 1) {
seconds = Integer.parseInt(parts[0]);
}
// if the array has only 2 cells that means there is only minutes and seconds input
if (parts.length == 2) {
minutes = Integer.parseInt(parts[0]);
seconds = Integer.parseInt(parts[1]);
}
// if the array has 3 cells that means there is seconds minutes and hours input
if (parts.length == 3) {
hours = Integer.parseInt(parts[0]);
minutes = Integer.parseInt(parts[1]);
seconds = Integer.parseInt(parts[2]);
}
// doesn't allow seconds minutes or hours to be negative
if (seconds < 0 || minutes < 0 || hours < 0) {
throw new IllegalArgumentException("Time cannot be negative");
}
// doesn't allow seconds to be greater than or equal to 60
if (seconds >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 seconds");
}
// doesn't allow minutes to be greater than or equal to 60
if (minutes >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 minutes");
}
}
/**************************************************************************************************
* Method that returns true or false based on whether or not two CountDownTimer objects are equal
* #param other Object that is being compared to another CountDownTimer
**************************************************************************************************/
public boolean equals(Object other) {
// converts the two objects to seconds then compares them
if (this.convertToSeconds() == ((CountDownTimer) other)
.convertToSeconds())
return true;
return false;
}
/********************************************************************************
* Returns a boolean based on whether two CountDownTimers, t1 and t2, are equal
* #param t1 first CountDownTimer being compared
* #param t2 second CountDownTimer being compared
********************************************************************************/
public static boolean equals(CountDownTimer t1, CountDownTimer t2) {
// converts the two objects to seconds and then compares them
if (t1.convertToSeconds() == t2.convertToSeconds())
return true;
return false;
}
/************************************************************************************************
* Compares to CountDownTimer objects and returns an int 1, 0, or -1 based on whether the first
* object is greater than, equal to, or less than the CountDownTimer in the parameter
* #param other CountDownTimer that is being compared
*************************************************************************************************/
public int compareTo(CountDownTimer other) {
if (this.convertToSeconds() > other.convertToSeconds())
return 1;
else if (this.convertToSeconds() < other.convertToSeconds())
return -1;
return 0;
}
/**************************************************************************************************
* Compares to CountDownTimer objects and returns an int 1, 0, or -1 based on whether the first
* object (t1) is greater than, equal to, or less than the second object (t2)
* #param t1 first object being compared
* #param t2 second object being compared
* #return
***************************************************************************************************/
public static int compareTo(CountDownTimer t1, CountDownTimer t2) {
if (t1.convertToSeconds() > t2.convertToSeconds())
return 1;
else if (t1.convertToSeconds() < t2.convertToSeconds())
return -1;
return 0;
}
/***************************************************************
* subtracts the input amount of seconds from a CountDownTimer
* #param seconds amount of seconds the user wants to subtract
***************************************************************/
public void subtract(int seconds) {
// places the amount of seconds into an integer
int tempSeconds = this.convertToSeconds();
// subtracts the input seconds from the seconds that were converted
tempSeconds -= seconds;
// converts the new seconds back into the object
formatSeconds(tempSeconds);
}
/*******************************************************************************************
* Subtracts the amount of time contained in one CountDownTimer from another CountDownTimer
* #param other CountDownTimer that is doing the subtracting
*******************************************************************************************/
public void subtract(CountDownTimer other) {
int otherSeconds = other.convertToSeconds();
this.subtract(otherSeconds);
}
/***********************************************************************
* Adds seconds to the object based on what is put into the parameter
* #param seconds amount of seconds being added to the CountDownTimer
************************************************************************/
public void add(int seconds) {
// keeps the method from adding when the toggle is activated
if (toggle == false) {
int tempSeconds = this.convertToSeconds();
tempSeconds += seconds;
formatSeconds(tempSeconds);
} else
throw new IllegalArgumentException(
"Cannot use add when toggle is enabled");
}
/**
* Adds the seconds from one CountDownTimer to another CountDownTimer
* #param other CountDownTimer that is being added to another CountDowntimer
*/
public void add(CountDownTimer other) {
// doesn't allow the method to add when the toggle is true
if (toggle == false) {
int otherSeconds = other.convertToSeconds();
this.add(otherSeconds);
} else
throw new IllegalArgumentException(
"Cannot use add when toggle is enabled");
}
/*******************************************
* Decreases the CountDownTimer by 1 second
*******************************************/
public void dec() {
int tempSeconds = this.convertToSeconds();
tempSeconds--;
formatSeconds(tempSeconds);
}
/****************************************************
* Increases the CountDownTimer object by 1 second
***************************************************/
public void inc() {
int tempSeconds = this.convertToSeconds();
tempSeconds--;
formatSeconds(tempSeconds);
}
/**
* Returns the object as a string in the format of "00:00:00"
*/
public String toString() {
String time = "" + this.hours + ":";
if (this.minutes < 10) {
time += "0" + this.minutes + ":";
} else {
time += this.minutes + ":";
}
if (this.seconds < 10) {
time += "0" + this.seconds;
} else {
time += this.seconds;
}
return time;
}
/************************************************
* Saves the object with a specified name
* #param fileName name of the file being saved
*************************************************/
public void save(String fileName) {
PrintWriter out = null;
try {
out = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
} catch (IOException e) {
e.printStackTrace();
}
out.println(this.hours);
out.println(this.minutes);
out.println(this.seconds);
out.close();
}
/**************************************************
* Loads the object with the specified name
* #param fileName Name of the file being loaded
**************************************************/
public void load(String fileName) {
try {
Scanner fileReader = new Scanner(new File(fileName));
this.hours = fileReader.nextInt();
this.minutes = fileReader.nextInt();
this.seconds = fileReader.nextInt();
fileReader.close();
System.out.println("Hours: " + this.hours);
System.out.println("Minutes: " + this.minutes);
System.out.println("Seconds: " + this.seconds);
} catch (FileNotFoundException error) {
System.out.println("File not found");
} catch (IOException error) {
System.out.println("OH NO THAT WAS NOT SUPPOSED TO HAPPEN");
}
}
/**********************************************************************************************
* Switches the toggle boolean, and doesn't allow the add methods to work when it is activated
************************************************************************************************/
public static void toggleSuspend() {
if (toggle == false)
toggle = true;
if (toggle == true)
toggle = false;
}
/***********************************************************************************
* Formats a certain amount of seconds and puts it into an existing CountDownTimer
* #param seconds seconds being formatted
***********************************************************************************/
private void formatSeconds(int seconds) {
this.hours = seconds / 3600;
seconds %= 3600;
this.minutes = seconds / 60;
this.seconds = seconds % 60;
}
/*****************************************************************************
* Returns the amount of seconds that are contained in a CountDownTime object
*****************************************************************************/
private int convertToSeconds() {
int hSeconds = hours * 3600;
int mSeconds = minutes * 60;
return hSeconds + mSeconds + seconds;
}
}
And here is my GUI panel class, where I'm having my problem. I'm using arrays to make multiple timers.
package pack1;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
public class MyTimerPanel extends JPanel {
/** Array of CountDownTimers that will be used */
private CountDownTimer[] cdt;
/** Array of Timer objects that are used to count down by 1 every second*/
private Timer[] javaTimer;
/** Array of TimerListeners that are called in the Timer objects */
private TimerListener timer[];
/** Array of JPanels that will hold each timer interface */
private JPanel[] panel;
/** Array of JLabels for the display of time, seconds, minutes, and hours */
private JLabel[] timeDisplay, secDisplay, minDisplay, hourDisplay;
/** Array of JButtons that start, stop, and set the timer */
private JButton[] start, stop, set;
/** Array of JTextFields that the user will input the seconds, minutes, and hours*/
private JTextField[] sec, min, hour;
/** Array of booleans that will determine if the timer should be counting down */
private boolean[] go;
/** Amount of milliseconds the timer needs to wait before performing an action */
private final int DELAY = 1000;
/** Amount of CountDownTimers in the interfaces */
private final int AMOUNT = 3;
// test integer
int[] count;
/******************************************************************************************
* Constructor that sets the lengths of the arrays and instantiates each part of the array
******************************************************************************************/
public MyTimerPanel() {
count = new int[AMOUNT];
timer = new TimerListener[AMOUNT];
cdt = new CountDownTimer[AMOUNT];
javaTimer = new Timer[AMOUNT];
panel = new JPanel[AMOUNT];
timeDisplay = new JLabel[AMOUNT];
secDisplay = new JLabel[AMOUNT];
minDisplay = new JLabel[AMOUNT];
hourDisplay = new JLabel[AMOUNT];
sec = new JTextField[AMOUNT];
min = new JTextField[AMOUNT];
hour = new JTextField[AMOUNT];
start = new JButton[AMOUNT];
stop = new JButton[AMOUNT];
set = new JButton[AMOUNT];
go = new boolean[AMOUNT];
// Defines each part of each array and adds the neccessary components to the buttons and panels
for (int i = 0; i < AMOUNT; i++) {
count[i] = 0;
cdt[i] = new CountDownTimer(0, 0, 0);
go[i] = false;
timer[i] = new TimerListener();
javaTimer[i] = new Timer(DELAY, timer[i]);
javaTimer[i].start();
timeDisplay[i] = new JLabel(cdt[i].toString());
secDisplay[i] = new JLabel("Seconds: ");
minDisplay[i] = new JLabel("Minutes: ");
hourDisplay[i] = new JLabel("Hours: ");
sec[i] = new JTextField(5);
min[i] = new JTextField(5);
hour[i] = new JTextField(5);
start[i] = new JButton("Start");
stop[i] = new JButton("Stop");
set[i] = new JButton("Set");
start[i].addActionListener(timer[i]);
stop[i].addActionListener(timer[i]);
set[i].addActionListener(timer[i]);
panel[i] = new JPanel();
panel[i].add(hourDisplay[i]);
panel[i].add(hour[i]);
panel[i].add(minDisplay[i]);
panel[i].add(min[i]);
panel[i].add(secDisplay[i]);
panel[i].add(sec[i]);
panel[i].add(start[i]);
panel[i].add(stop[i]);
panel[i].add(set[i]);
panel[i].add(timeDisplay[i]);
add(panel[i]);
}
setPreferredSize(new Dimension(750, 40 * AMOUNT));
}
/*******************************************************************
* Action Listener that activates when certain buttons are pressed
*******************************************************************/
private class TimerListener implements ActionListener {
/********************************************************************
* ActionListener that is activated whenever someone pushes a button
********************************************************************/
public void actionPerformed(ActionEvent e) {
// CountDownTimer that will be compared to at zero
CountDownTimer zero = new CountDownTimer();
// placeholders for the text from the JTextFields
String[] secText = new String[AMOUNT];
String[] minText = new String[AMOUNT];
String[] hourText = new String[AMOUNT];
// runs through each part of the arrays and checks which button needs to be pressed
for (int i = 0; i < AMOUNT; i++) {
// checks if one of the start buttons is being pressed
if (e.getSource() == start[i]){
go[i] = true;
}
// checks if one of the stop buttons is being pressed
else if (e.getSource() == stop[i])
go[i] = false;
// checks if one of the set buttons is being pressed and sets the minutes hours and seconds input
if (e.getSource() == set[i]) {
secText[i] = sec[i].getText();
minText[i] = min[i].getText();
hourText[i] = hour[i].getText();
// if one of the boxes is blank, it will input zero
if (secText[i].equals("")) {
cdt[i].seconds = 0;
} else {
cdt[i].seconds = Integer.parseInt(secText[i]);
}
if (minText[i].equals("")) {
cdt[i].minutes = 0;
} else {
cdt[i].minutes = Integer.parseInt(minText[i]);
}
if (hourText[i].equals("")) {
cdt[i].hours = 0;
} else {
cdt[i].hours = Integer.parseInt(hourText[i]);
}
// sets timeDisplay to show the time in the countdowntimer
timeDisplay[i].setText(cdt[i].toString());
// stops the timer after setting it
go[i] = false;
}
// the timer should be counting down if the go boolean is true or the countdowntimer isn't zero
if (go[i] == true && !cdt[i].equals(zero)) {
javaTimer[i].start();
cdt[i].dec();
timeDisplay[i].setText(cdt[i].toString());
count[i]++;
}
// the timer shouldn't be counting down if the go boolean is false or the countdowntimer is zero
if (go[i] == false || cdt[i].compareTo(zero) <= 0) {
javaTimer[i].stop();
}
}
// for testing purposes
System.out.println(count[0] + "\t" + count[1] + "\t" + count[2]);
}
}
}
The problem is with your TimerListener.
Basically, what's happening, is each time it is called, it executes this code block...
if (go[i] == true && !cdt[i].equals(zero)) {
javaTimer[i].start();
cdt[i].dec();
timeDisplay[i].setText(cdt[i].toString());
count[i]++;
}
This means, if you have 3 counters running, this code block will be executed 9 times per second. Three times per counter/Timer
You TimerListener is too generalised and is trying to do too many things.
Either, create a "single" Timer that ticks on a regular bases and updates each counter as required (so that each loop is dealing with a single counter) OR modify your TimerListener so that it takes details about the counter it is managing and deals ONLY with that counter.
Updated with possible solution
This example uses a single, centralised Timer which simply ticks away in the background. As required, a special Counter is registered with the Timer, which then notifies it when a tick occurs. The Counter then decrements the CountDownTimer and updates the UI.
This is an imperfect example, as I would prefer that the CountDownTimer had a listener interface capable of notifying registered listeners that object's state has changed in some way. This could be achieved through the wrapper Counter class, but I'm to lazy.
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestTimerPane {
public static void main(String[] args) {
new TestTimerPane();
}
public TestTimerPane() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
CountDownManager countDownManager = new CountDownManager();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
frame.add(new TimerPane(countDownManager), gbc);
frame.add(new TimerPane(countDownManager), gbc);
frame.add(new TimerPane(countDownManager), gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class CountDownManager {
private List<Counter> timers;
public CountDownManager() {
timers = new ArrayList<>(25);
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Iterator<Counter> it = timers.iterator();
while (it.hasNext()) {
it.next().tick(CountDownManager.this);
}
}
});
timer.start();
}
public void add(Counter timer) {
timers.add(timer);
}
public void remove(Counter timer) {
timers.remove(timer);
}
}
public class TimerPane extends JPanel {
private JTextField fldHours;
private JTextField fldMins;
private JTextField fldSecs;
private JButton btnStart;
private JButton btnStop;
private JButton btnSet;
private JLabel countDown;
private CountDownTimer countDownTimer;
private Counter counter;
public TimerPane(final CountDownManager countDownManager) {
fldHours = new JTextField(2);
fldMins = new JTextField(2);
fldSecs = new JTextField(2);
btnSet = new JButton("Set");
btnStop = new JButton("Stop");
btnStart = new JButton("Start");
countDown = new JLabel("??:??:??");
add(fldHours);
add(new JLabel(":"));
add(fldMins);
add(new JLabel(":"));
add(fldSecs);
add(btnSet);
add(btnStart);
add(btnStop);
add(countDown);
btnSet.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
countDownTimer = new CountDownTimer(
toInt(fldHours),
toInt(fldMins),
toInt(fldSecs));
counter = new Counter(countDown, countDownTimer);
countDown.setText(countDownTimer.toString());
}
});
btnStart.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (counter != null) {
countDownManager.add(counter);
}
}
});
btnStop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (counter != null) {
countDownManager.remove(counter);
}
}
});
}
protected int toInt(JTextField field) {
int value = 0;
try {
value = Integer.parseInt(field.getText());
} catch (NumberFormatException exp) {
}
return value;
}
}
public class Counter {
private JLabel output;
private CountDownTimer timer;
public Counter(JLabel output, CountDownTimer timer) {
this.output = output;
this.timer = timer;
}
public void tick(CountDownManager manager) {
timer.dec();
output.setText(timer.toString());
if (timer.convertToSeconds() <= 0) {
manager.remove(this);
}
}
}
public static class CountDownTimer {
/**
* Amount of hours that are being counted down in the timer
*/
int hours;
/**
* Amount of minutes that are being counted down in the timer
*/
int minutes;
/**
* Amount of seconds that are being counted down in the timer
*/
int seconds;
/**
* Boolean that determines if the add method will work. It is changed with
* the toggleSuspend method
*/
static boolean toggle = false;
/**
* ***************************************************************************************
* Default constructor that creates a CountDownTimer object with no time
* contained in it
* ***************************************************************************************
*/
public CountDownTimer() {
hours = 0;
minutes = 0;
seconds = 0;
}
/**
* *******************************************************************************************
* Constructor that uses the input amount of hours, minutes, and seconds to
* count down from
*
* Does not allow time that is negative or allow seconds or minutes that are
* over 60
*
* #param hours amount of hours that will be counted down from
* #param minutes amount of minutes that will be counted down from
* #param seconds amount of seconds that will be counted down from
* *******************************************************************************************
*/
public CountDownTimer(int hours, int minutes, int seconds) {
super();
// doesn't allow negative minutes, seconds, or hours
if (seconds < 0 || minutes < 0 || hours < 0) {
throw new IllegalArgumentException("Time cannot be negative");
}
// doesn't allow seconds that are higher than 60
if (seconds >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 seconds");
}
// doesn't allow minutes that are higher than 60
if (minutes >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 minutes");
}
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
}
/**
* *******************************************************************
* Constructor that takes minutes and seconds, and sets hours to zero also
* doesn't allow minutes or seconds to be negative or above 60
*
* #param minutes amount of minutes that will be counted down from
* #param seconds amount of seconds that will be counted down from
* ***********************************************************************
*/
public CountDownTimer(int minutes, int seconds) {
super();
// doesn't allow seconds minutes or hours to be negative
if (seconds < 0 || minutes < 0 || hours < 0) {
throw new IllegalArgumentException("Time cannot be negative");
}
// doesn't allow seconds to be greater than 60
if (seconds >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 seconds");
}
// doesn't allow minutes to be greater than 60
if (minutes >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 minutes");
}
this.hours = 0;
this.minutes = minutes;
this.seconds = seconds;
}
/**
* *********************************************************************
* Constructor that only takes seconds and sets hours and minutes to 0 does
* not allow the seconds to be above 60 or negative
*
* #param seconds amount of seconds that will be counted down from
* ***********************************************************************
*/
public CountDownTimer(int seconds) {
super();
// doesn't allow seconds minutes or hours to be negative
if (seconds < 0 || minutes < 0 || hours < 0) {
throw new IllegalArgumentException("Time cannot be negative");
}
// doesn't allow seconds to be greater than 60
if (seconds >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 seconds");
}
this.hours = 0;
this.minutes = 0;
this.seconds = seconds;
}
/**
* Constructor that clones one CountDownTimer object into a new
* CountDownTimer object
*
* #param other The CountDownTimer object that is being cloned
*
*/
public CountDownTimer(CountDownTimer other) {
this.hours = other.hours;
this.minutes = other.minutes;
this.seconds = other.seconds;
}
/**
* *****************************************************************************************************************************
* Constructor that converts a string in the format of "00:00:00" into
* seconds minutes and hours so it can be counted down from
*
* #param startTime String that is converted into seconds minutes and hours
* *****************************************************************************************************************************
*/
public CountDownTimer(String startTime) {
// Separates the seconds minutes and hours into an array
String[] parts = startTime.split(":");
// if the array has only one cell, that means only seconds were input
if (parts.length == 1) {
seconds = Integer.parseInt(parts[0]);
}
// if the array has only 2 cells that means there is only minutes and seconds input
if (parts.length == 2) {
minutes = Integer.parseInt(parts[0]);
seconds = Integer.parseInt(parts[1]);
}
// if the array has 3 cells that means there is seconds minutes and hours input
if (parts.length == 3) {
hours = Integer.parseInt(parts[0]);
minutes = Integer.parseInt(parts[1]);
seconds = Integer.parseInt(parts[2]);
}
// doesn't allow seconds minutes or hours to be negative
if (seconds < 0 || minutes < 0 || hours < 0) {
throw new IllegalArgumentException("Time cannot be negative");
}
// doesn't allow seconds to be greater than or equal to 60
if (seconds >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 seconds");
}
// doesn't allow minutes to be greater than or equal to 60
if (minutes >= 60) {
throw new IllegalArgumentException(
"Cannot have more than 60 minutes");
}
}
/**
* ************************************************************************************************
* Method that returns true or false based on whether or not two
* CountDownTimer objects are equal
*
* #param other Object that is being compared to another CountDownTimer
* ************************************************************************************************
*/
public boolean equals(Object other) {
// converts the two objects to seconds then compares them
if (this.convertToSeconds() == ((CountDownTimer) other)
.convertToSeconds()) {
return true;
}
return false;
}
/**
* ******************************************************************************
* Returns a boolean based on whether two CountDownTimers, t1 and t2, are
* equal
*
* #param t1 first CountDownTimer being compared
* #param t2 second CountDownTimer being compared
* ******************************************************************************
*/
public static boolean equals(CountDownTimer t1, CountDownTimer t2) {
// converts the two objects to seconds and then compares them
if (t1.convertToSeconds() == t2.convertToSeconds()) {
return true;
}
return false;
}
/**
* **********************************************************************************************
* Compares to CountDownTimer objects and returns an int 1, 0, or -1 based
* on whether the first object is greater than, equal to, or less than the
* CountDownTimer in the parameter
*
* #param other CountDownTimer that is being compared
* ***********************************************************************************************
*/
public int compareTo(CountDownTimer other) {
if (this.convertToSeconds() > other.convertToSeconds()) {
return 1;
} else if (this.convertToSeconds() < other.convertToSeconds()) {
return -1;
}
return 0;
}
/**
* ************************************************************************************************
* Compares to CountDownTimer objects and returns an int 1, 0, or -1 based
* on whether the first object (t1) is greater than, equal to, or less than
* the second object (t2)
*
* #param t1 first object being compared
* #param t2 second object being compared
* #return
* *************************************************************************************************
*/
public static int compareTo(CountDownTimer t1, CountDownTimer t2) {
if (t1.convertToSeconds() > t2.convertToSeconds()) {
return 1;
} else if (t1.convertToSeconds() < t2.convertToSeconds()) {
return -1;
}
return 0;
}
/**
* *************************************************************
* subtracts the input amount of seconds from a CountDownTimer
*
* #param seconds amount of seconds the user wants to subtract
* *************************************************************
*/
public void subtract(int seconds) {
// places the amount of seconds into an integer
int tempSeconds = this.convertToSeconds();
// subtracts the input seconds from the seconds that were converted
tempSeconds -= seconds;
// converts the new seconds back into the object
formatSeconds(tempSeconds);
}
/**
* *****************************************************************************************
* Subtracts the amount of time contained in one CountDownTimer from another
* CountDownTimer
*
* #param other CountDownTimer that is doing the subtracting
* *****************************************************************************************
*/
public void subtract(CountDownTimer other) {
int otherSeconds = other.convertToSeconds();
this.subtract(otherSeconds);
}
/**
* *********************************************************************
* Adds seconds to the object based on what is put into the parameter
*
* #param seconds amount of seconds being added to the CountDownTimer
* **********************************************************************
*/
public void add(int seconds) {
// keeps the method from adding when the toggle is activated
if (toggle == false) {
int tempSeconds = this.convertToSeconds();
tempSeconds += seconds;
formatSeconds(tempSeconds);
} else {
throw new IllegalArgumentException(
"Cannot use add when toggle is enabled");
}
}
/**
* Adds the seconds from one CountDownTimer to another CountDownTimer
*
* #param other CountDownTimer that is being added to another CountDowntimer
*/
public void add(CountDownTimer other) {
// doesn't allow the method to add when the toggle is true
if (toggle == false) {
int otherSeconds = other.convertToSeconds();
this.add(otherSeconds);
} else {
throw new IllegalArgumentException(
"Cannot use add when toggle is enabled");
}
}
/**
* *****************************************
* Decreases the CountDownTimer by 1 second
* *****************************************
*/
public void dec() {
int tempSeconds = this.convertToSeconds();
tempSeconds--;
formatSeconds(tempSeconds);
}
/**
* **************************************************
* Increases the CountDownTimer object by 1 second
* *************************************************
*/
public void inc() {
int tempSeconds = this.convertToSeconds();
tempSeconds--;
formatSeconds(tempSeconds);
}
/**
* Returns the object as a string in the format of "00:00:00"
*/
public String toString() {
String time = "" + this.hours + ":";
if (this.minutes < 10) {
time += "0" + this.minutes + ":";
} else {
time += this.minutes + ":";
}
if (this.seconds < 10) {
time += "0" + this.seconds;
} else {
time += this.seconds;
}
return time;
}
/**
* **********************************************
* Saves the object with a specified name
*
* #param fileName name of the file being saved
* ***********************************************
*/
public void save(String fileName) {
PrintWriter out = null;
try {
out = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
} catch (IOException e) {
e.printStackTrace();
}
out.println(this.hours);
out.println(this.minutes);
out.println(this.seconds);
out.close();
}
/**
* ************************************************
* Loads the object with the specified name
*
* #param fileName Name of the file being loaded
* ************************************************
*/
public void load(String fileName) {
try {
Scanner fileReader = new Scanner(new File(fileName));
this.hours = fileReader.nextInt();
this.minutes = fileReader.nextInt();
this.seconds = fileReader.nextInt();
fileReader.close();
System.out.println("Hours: " + this.hours);
System.out.println("Minutes: " + this.minutes);
System.out.println("Seconds: " + this.seconds);
} catch (FileNotFoundException error) {
System.out.println("File not found");
} catch (IOException error) {
System.out.println("OH NO THAT WAS NOT SUPPOSED TO HAPPEN");
}
}
/**
* ********************************************************************************************
* Switches the toggle boolean, and doesn't allow the add methods to work
* when it is activated
* **********************************************************************************************
*/
public static void toggleSuspend() {
if (toggle == false) {
toggle = true;
}
if (toggle == true) {
toggle = false;
}
}
/**
* *********************************************************************************
* Formats a certain amount of seconds and puts it into an existing
* CountDownTimer
*
* #param seconds seconds being formatted
* *********************************************************************************
*/
private void formatSeconds(int seconds) {
this.hours = seconds / 3600;
seconds %= 3600;
this.minutes = seconds / 60;
this.seconds = seconds % 60;
}
/**
* ***************************************************************************
* Returns the amount of seconds that are contained in a CountDownTime
* object
* ***************************************************************************
*/
private int convertToSeconds() {
int hSeconds = hours * 3600;
int mSeconds = minutes * 60;
return hSeconds + mSeconds + seconds;
}
}
}
Now, if you need a separate Timer per CountDownTimer, then I would probably create some kind of "worker" class that would take a CountDownTimer and that had a self contained Timer. I would also provide some kind of listener that interested parties could register to and would allow them to update the UI as they see fit...
I have the required code for the stopwatch here. All i want is get rid of the Swing part here and display the same output in console. Can anybody help?
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.text.*;
public class ElapsedTime extends JFrame
{
JLabel time;
long startTime = System.currentTimeMillis();
ElapsedTime()
{
setSize(380,200);
setTitle("http://simpleandeasycodes.blogspot.com/");
setLocation(100,100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridBagLayout());
time = new JLabel("");
time.setFont(new Font("SansSerif",Font.BOLD, 36));
time.setForeground(Color.MAGENTA);
add(time);
//starting new Thread which will update time
new Thread(new Runnable()
{
public void run()
{ try
{
updateTime();
}
catch (Exception ie)
{ }
}
}).start();
}
public void updateTime()
{
try
{
while(true)
{
//geting Time in desire format
time.setText(getTimeElapsed());
//Thread sleeping for 1 sec
Thread.currentThread().sleep(1000);
}
}
catch (Exception e)
{
System.out.println("Exception in Thread Sleep : "+e);
}
}
public String getTimeElapsed()
{
long elapsedTime = System.currentTimeMillis() - startTime;
elapsedTime = elapsedTime / 1000;
String seconds = Integer.toString((int)(elapsedTime % 60));
String minutes = Integer.toString((int)((elapsedTime % 3600) / 60));
String hours = Integer.toString((int)(elapsedTime / 3600));
if (seconds.length() < 2)
seconds = "0" + seconds;
if (minutes.length() < 2)
minutes = "0" + minutes;
if (hours.length() < 2)
hours = "0" + hours;
return minutes+":"+seconds;
}
public static void main(String[] args)
{
JFrame obj = new ElapsedTime();
obj.setVisible(true);
}
}
The keys are:
a.) Finding which character to write to the console in order to remove the most recently-written character (\b, or \010 in ASCII)
b.) Realising that you need to remember how many characters you've written to the console the last time you updated it
c.) Remembering to use print instead of println
public class Test {
public static void main(String[] args) throws InterruptedException {
int charsWritten = 0;
long start = System.currentTimeMillis();
while (1 > 0) {
Thread.sleep(1000);
long elapsedTime = System.currentTimeMillis() - start;
elapsedTime = elapsedTime / 1000;
String seconds = Integer.toString((int) (elapsedTime % 60));
String minutes = Integer.toString((int) ((elapsedTime % 3600) / 60));
String hours = Integer.toString((int) (elapsedTime / 3600));
if (seconds.length() < 2) {
seconds = "0" + seconds;
}
if (minutes.length() < 2) {
minutes = "0" + minutes;
}
if (hours.length() < 2) {
hours = "0" + hours;
}
String writeThis = hours + ":" + minutes + ":" + seconds;
for (int i = 0; i < charsWritten; i++) {
System.out.print("\b");
}
System.out.print(writeThis);
charsWritten = writeThis.length();
}
}
}
Note: you could be more efficient by only clearing the console up to only the characters you are changing but I figure you're not going to get that much of a speed improvement.
Have a look at StopWatch from Apache Commons. It should fulfill your needs.
Here's something that i have figured out myself a little while ago:
public class DelayExample{
static int i,j;
public static void main(String[] args){
for (j= 0; j>=0; j++)
{
for (i = 0; i < 60; i++)
{
System.out.println(j+":" + i);
try
{
Thread.sleep(1000);
}catch (InterruptedException ie)
{
System.out.println(ie.getMessage());
}
}
}
}
}
Now i want the clear screen code in Java now. Also i think i have to use System.out.print() instead.
So there a Swing-free solution:
public class ElapsedTime{
long startTime = System.currentTimeMillis();
public ElapsedTime() {
try {
while (true) {
//Clear Console
for (int i = 0; i < 25; i++)
System.out.println();
// geting Time in desire format
System.out.println(getTimeElapsed());
// Thread sleeping for 1 sec
Thread.currentThread().sleep(1000);
}
} catch (Exception e) {
System.out.println("Exception in Thread Sleep : " + e);
}
}
public String getTimeElapsed() {
long elapsedTime = System.currentTimeMillis() - startTime;
elapsedTime = elapsedTime / 1000;
String seconds = Integer.toString((int) (elapsedTime % 60));
String minutes = Integer.toString((int) ((elapsedTime % 3600) / 60));
String hours = Integer.toString((int) (elapsedTime / 3600));
if (seconds.length() < 2)
seconds = "0" + seconds;
if (minutes.length() < 2)
minutes = "0" + minutes;
if (hours.length() < 2)
hours = "0" + hours;
return minutes + ":" + seconds;
}
public static void main(String[] args) {
new ElapsedTime();
}
}
I'm afraid there is no method to clear the console because Java is platform independant. I just insert 25 empty Lines so the last time disappears.