I want to print the time between two buttons clicks (ButtonA and ButtonB). This is part of my code (which doesn't work because only the current time is printed):
class ClicksReporter implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
long startTime = 0;
long endTime = 0;
if ( e.getActionCommand().equals("ButtonA") ) {
System.out.println("ButtonA was clicked");
startTime = System.currentTimeMillis()/1000;
}
if ( e.getActionCommand().equals("ButtonB") ) {
System.out.println("ButtonB was clicked");
endTime = System.currentTimeMillis()/1000 - startTime;
System.out.println("Time: "+endTime);
}
}
How can I solve this?
startTime and endTime are local variables that are lost once the method returns. So, every time ButtonB is clicked, the value of startTime is zero. You need to make start time a field of the class instead.So, something like this:
class ClicksReporter implements ActionListener {
long startTime=0;
#Override
public void actionPerformed(ActionEvent e) {
if ( e.getActionCommand().equals("ButtonA") ) {
System.out.println("ButtonA was clicked");
this.startTime = System.currentTimeMillis()/1000;
}
if ( e.getActionCommand().equals("ButtonB") ) {
System.out.println("ButtonB was clicked");
long endTime = System.currentTimeMillis()/1000 - startTime;
System.out.println("Time: "+endTime);
}
}
Also, make sure that the same instance of ClicksReporter is set as the action listener for both button A and B.
Related
I'm writing my first project in java, and I could use some help and experienced view. I'm trying to write stopWatch class, or something more like kitchen timer, which can provide this functionality:
- set hard start and end times,
- pause and start time from same place
- set if the time is decreasing or increasing
- move in Time up and down
- addTime (example: watch suppose to start at 00:00 end in 30:00 if we add 35 seconds stopWatch will end at 30:35);
- display time every second
I didn't find any good thread about this kind of stopWatch/kitchen timer here on stack overflow. My code is working, but I don't really have much of experience with OOD and java generally, so I'm expecting some flaws. It would be reasonable to use some pre-written classes instead? Or Date for time operation?
My code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
// class for handle timer operation
public class stopWatch implements ActionListener {
public Timer timer; // timer object
private int startTime; // start time in seconds
private int endTime; // end time in seconds
private int actualTime; // actual time in seconds
private long memoryUnixTime; // actual time in Unix format
private boolean decrease; // is Timer decrease or incerease Time?
private int presize; // how often timer check for change of time
// construct
public stopWatch(int startTime, int endTime, boolean decrease, int presize){
this.startTime = startTime;
this.endTime = endTime;
this.decrease = decrease;
this.presize = presize;
this.actualTime = startTime;
}
// moving in Time UP
public void moveTimeUp (int seconds){
if(inScope("up",seconds))
actualTime += seconds;
}
// moving in Time DOWN
public void moveTimeDown (int seconds){
if(inScope("down",seconds))
actualTime -= seconds;
}
// is added time still inScope
private boolean inScope(String direction,int seconds){
boolean inScopeP;
switch(direction){
case "up":
inScopeP = ((this.actualTime + seconds) <= this.endTime);
break;
case "down":
inScopeP = ((this.actualTime - seconds) >= this.startTime);
break;
default:
inScopeP = false;
break;
}
return inScopeP;
}
// addTime - this option will be used only if we use increasing timer
public void addTime(int seconds){
if(this.decrease == false)
this.endTime += seconds;
}
// run stopwatch
public void run(){
System.out.println("start");
this.timer = new Timer(this.presize, this);
this.timer.setRepeats(true);
this.timer.start();
}
//stop stopwatch
public void pause(){
this.timer.stop();
this.timer = null;
}
// end of counting
public void end(){
System.out.println("END");
this.pause();
}
// event listener, handle change time
#Override
public void actionPerformed(ActionEvent e) {
// If the timer caused this event.
if (e.getSource().equals(timer)) {
long currentTime = System.currentTimeMillis();
// If time had change we decrease or increase time and print it out
if(changeTimeP(currentTime)){
// if time`s up we end the counting
if(this.actualTime == this.endTime){
this.end();
// else we do the math increase
} else{
this.memoryUnixTime = currentTime/1000;
if(decrease == true)
{
this.actualTime--;
} else {
this.actualTime++;
}
// println into console for testing purposes
int min = this.actualTime / 60;
int sec = this.actualTime % 60;
System.out.println(min+":"+sec);
}
}
}
}
// did time changed? (in matter of one second)
private boolean changeTimeP(long currentTime){
if(this.memoryUnixTime != (currentTime/1000L))
return true;
else return false;
}
}
Peter
I'm trying to make a stopwatch that constantly updates to the screen what the time is. The time object is a JLabel that should display the time elapsed. I have everything imported and set up right, but whenever the start button is clicked to activate the timer, the program freezes.
public class Timing
{
public void Timer()
{
startTime = System.currentTimeMillis();
while(isTiming == true)
{
endTime = System.currentTimeMillis();
elapsedTime = endTime - startTime;
time.setText("" + elapsedTime);
info.validate();
}
endTime = System.currentTimeMillis();
elapsedTime = endTime - startTime;
time.setText("" + elapsedTime);
info.validate();
}
}
Here's the Action Listener part:
public void actionPerformed(ActionEvent arg0)
{
if(((JButton) arg0.getSource()).getText().equals("Start"))
{
isTiming = true;
new Timing().Timer();
}
You are trying to synchronously update your label in a loop in the UI thread, the same thread which is used for applying UI updates. By doing this you are blocking the execution which results into the freeze you are describing.
To resolve this, you could use the javax.swing.Timer to schedule the updates so that they would be run in the same UI thread, but only when needed, i.e.
timer = new javax.swing.Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
...
time.setText("" + elapsedTime);;
}
});
...
public void actionPerformed(ActionEvent arg0)
{
if(((JButton) arg0.getSource()).getText().equals("Start"))
{
isTiming = true;
timer.start();
}
}
I am new to countdown timer so I have no idea about this issue. I tried many things but I didn't get what I expected.
This is my code for the timer. It is a class within a class as usual.
// TIMER
public class Timer extends CountDownTimer {
public Timer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
//getNgo(true, score, tries, secLeft);
}
#Override
public void onTick(long millisUntilFinished) {
//secLeft = millisUntilFinished;
int sec = (int) (millisUntilFinished / 1000);
sec = sec % 60;
int min = sec / 60;
tvTime.setTextColor(Color.WHITE);
if (sec <= 10) {
animScale(tvTime);
tvTime.setTextColor(Color.RED);
tvTime.setText("" + min + ":" + sec);
if (sec < 10) {
tvTime.setTextColor(Color.RED);
tvTime.setText("" + min + ":0" + sec);
}
} else {
tvTime.setText("" + min + ":" + sec);
}
}
}
So, I just wanted to know how to deduct 3 seconds (that will be 3000 ms) when I push the button and the timer that is displayed by the textview will go on ticking but the time has already been deducted. And where do I put the code. Thanks!
When I've had to do this with tasks scheduled to take place in a fixed time, I've:
Cancelled the original task.
Submitted a new one with the new time period.
I suspect that this is a more standard pattern than your use of Timer anyway.
e.g.:
private final Runnable task = new Runnable() { #Override public void run() { /* ... */ } };
private final ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor();
private final long initialSeconds = 3;
public void submitTask() {
stpe.schedule(task, initialSeconds, TimeUnit.Seconds());
}
public void subtractSeconds(long sec) {
if(stpe.remove(task)) {
stpe.schedule(task, Math.Max(initialSeconds - sec, 0), TimeUnit.Seconds);
}
}
You will need to figure out:
how to ensure task is only initially-submitted once and keep track of fixed variable
whether you need one fixed final task or that task to be changed
concurrency/multithreading issues if the task can be submitted more than once
I've implemented a simple countdown using one of the stackoverflow posts
// gets current time
long timeNow = System.currentTimeMillis();
/* timer holds the values of the current second the timer should display
* requiredTime is the start value that the countdown should start from
* startTime is the time when the application starts
*/
timer = requiredTime - (timeNow - startTime) / 1000;
if (timer >= 0)
timer.setText(String.valueOf(timer));
To subtract the timer, subtract requiredTime and it will work. Because you've changed the reference value.
// Override onClickListener and add the line
// to deduct 3 seconds
requiredTime -= 3;
You can't. You have to write your own CountDownTimer. Copy original code and add method
public synchronized void addTime(long millis) {
mStopTimeInFuture += millis;
}
Then set onClickListener to the button
bt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
timer.addTime(-2000);
}
});
Here is full sample code
I'm wanting to create a stopwatch so to speak in order to score my game. Lets say I have a variable: int sec = 0. When the game starts I want a g.drawString to draw the time to the applet. So for example each second, sec will increment by 1.
How do I go about making it g.drawString(Integer.toString(sec), 40, 400) increment by 1 and draw each second?
Thanks.
EDIT:
I've figured out how to increment it and print it to the screen by using ActionListener and putting g.drawString in there but it prints ontop of each other. If I put g.drawString into the paint method and only increment sec by 1 in the ActionListener there is a a flicker. Should I use Double Buffering? If so how do I go about doing this?
import java.awt.event.*;
import javax.swing.*;
public class StopWatch extends JLabel
implements MouseListener, ActionListener {
private long startTime; // Start time of stopwatch.
// (Time is measured in milliseconds.)
private boolean running; // True when the stopwatch is running.
private Timer timer; // A timer that will generate events
// while the stopwatch is running
public StopWatch() {
// Constructor.
super(" Click to start timer. ", JLabel.CENTER);
addMouseListener(this);
}
public void actionPerformed(ActionEvent evt) {
// This will be called when an event from the
// timer is received. It just sets the stopwatch
// to show the amount of time that it has been running.
// Time is rounded down to the nearest second.
long time = (System.currentTimeMillis() - startTime) / 1000;
setText("Running: " + time + " seconds");
}
public void mousePressed(MouseEvent evt) {
// React when user presses the mouse by
// starting or stopping the stopwatch. Also start
// or stop the timer.
if (running == false) {
// Record the time and start the stopwatch.
running = true;
startTime = evt.getWhen(); // Time when mouse was clicked.
setText("Running: 0 seconds");
if (timer == null) {
timer = new Timer(100,this);
timer.start();
}
else
timer.restart();
}
else {
// Stop the stopwatch. Compute the elapsed time since the
// stopwatch was started and display it.
timer.stop();
running = false;
long endTime = evt.getWhen();
double seconds = (endTime - startTime) / 1000.0;
setText("Time: " + seconds + " sec.");
}
}
public void mouseReleased(MouseEvent evt) { }
public void mouseClicked(MouseEvent evt) { }
public void mouseEntered(MouseEvent evt) { }
public void mouseExited(MouseEvent evt) { }
} // end StopWatchRunner
A small applet to test the component:
/*
A trivial applet that tests the StopWatchRunner component.
The applet just creates and shows a StopWatchRunner.
*/
import java.awt.*;
import javax.swing.*;
public class Test1 extends JApplet {
public void init() {
StopWatch watch = new StopWatch();
watch.setFont( new Font("SansSerif", Font.BOLD, 24) );
watch.setBackground(Color.white);
watch.setForeground( new Color(180,0,0) );
watch.setOpaque(true);
getContentPane().add(watch, BorderLayout.CENTER);
}
}
I created a game and in my swing GUI interface I want to put a timer. The way I do this at the moment is have a field with the current time , gotten with System.currentTimeMillis() which gets it's value when the game starts .In the method of my game i put the System.currentTimeMillis()- field; and it tells you the current time passed since the game started.
Nevertheless, how do get this to update itself every second lets say, so the JLabel will have : timePassed: 0s , timePassed: 1s and so on. Have in mind that i don't use threads in my game at any point.
EDIT: thank you all for your kind suggestions. I used a combination of your answers please give me some feedback.
I have the JLabel as a field called time. (else i cant handle it).
time = new JLabel("Time Passed: " + timePassed() + " sec");
panel_4.add(time);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
time.setText("Time Passed: " + timePassed() + " sec");
}
};
Timer timer = new Timer(1000, actionListener);
timer.start();
Have a look at the swing timer class. It allows to setup recurring tasks quite easily.
This is how I would set my JLabel to update with time & date.
Timer SimpleTimer = new Timer(1000, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
jLabel1.setText(SimpleDay.format(new Date()));
jLabel2.setText(SimpleDate.format(new Date()));
jLabel3.setText(SimpleTime.format(new Date()));
}
});
SimpleTimer.start();
This is then added to your main class and the jlabel1/2/3 get updated with the timer.
new Thread(new Runnable
{
public void run()
{
long start = System.currentTimeMillis();
while (true)
{
long time = System.currentTimeMillis() - start;
int seconds = time / 1000;
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
label.setText("Time Passed: " + seconds);
}
});
try { Thread.sleep(100); } catch(Exception e) {}
}
}
}).start();
wirite this in Constructor
ActionListener taskPerformer = new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
jMenu11.setText(CurrentTime());
}
};
Timer t = new Timer(1000, taskPerformer);
t.start();
And this Write out Constructor
public String CurrentTime(){
Calendar cal = new GregorianCalendar();
int second = cal.get(Calendar.SECOND);
int min = cal.get(Calendar.MINUTE);
int hour = cal.get(Calendar.HOUR);
String s=(checkTime(hour)+":"+checkTime(min)+":"+checkTime(second));
jMenu11.setText(s);
return s;
}
public String checkTime(int t){
String time1;
if (t < 10){
time1 = ("0"+t);
}
else{
time1 = (""+t);
}
return time1;
}