I'm writing the code of my first Java Game right now, so far I have built GUI and I want to add some logic. In my game, user should see elapsing time for his move (begin with 10s), like 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0. I created JLabel and would like to display that elapsing time on it. My program has 3 levels of difficulty, firstly user chooses one by clicking on appropriate JButton and then user should see the timer and some options to choice and play. How can i cope with this problem? I read about Timer class in Java but still don't know how can i display counting-down time on JLabel. Maybe should I implement a game loop, but to be honest I don't have any idea how to make it.
You can simply use a count down timer method and pass your JLabel to it along with the number of seconds to count down and a optional 'End Of Time' message.
There are lots of examples of this sort of thing on the internet but here is my quick rendition of one:
public static Timer CountdownTimer(JLabel comp, int secondsDuration, String... endOfTimeMessage) {
if (secondsDuration == 0) { return null; }
String endMsg = "~nothing~";
if (endOfTimeMessage.length>0) { endMsg = endOfTimeMessage[0]; }
final String eMsg = endMsg;
int seconds = secondsDuration;
final long duration = seconds * 1000;
JLabel label = (JLabel)comp;
final Timer timer = new Timer(10, new ActionListener() {
long startTime = -1;
#Override
public void actionPerformed(ActionEvent event) {
if (startTime < 0) {
startTime = System.currentTimeMillis();
}
long now = System.currentTimeMillis();
long clockTime = now - startTime;
if (clockTime >= duration) {
((Timer)event.getSource()).stop();
if (!eMsg.equals("~nothing~")) { label.setText(eMsg); }
return;
}
SimpleDateFormat df = new SimpleDateFormat("mm:ss:SSS");
label.setText(df.format(duration - clockTime));
}
});
timer.start();
return timer;
}
If you want to change the way the count-down is displayed within the JLabel then you can change the SimpleDateFormat string. This method returns the Timer object so...you figure out how to stop it whenever you want (before the duration has expired).
Related
I'm trying to make an image twinkle with RaffleImage(); while I'm executing the timer, my character is immune to any collision, I want it to be immune only for 2 seconds, so the timer get execute only for 2 seconds and then get finished.
I've tried subtracting System.currentTimeMillis() but any variable I create from this method, have always the same value, making me get a zero from that subtracting.
Do you know how I can stop or pause the timer after any elapsed time in seconds?
immuneTimer = new Timer(50, new ActionListener() {
#Override
public synchronized void actionPerformed(ActionEvent e) {
long initMillis = System.currentTimeMillis();
if (System.currentTimeMillis() - initMillis > 2000 ) { // this substract gives me 0
initImages();
setImmune(false); // so this never reached
immuneTimer.stop();
} else {
raffleImage(); //its executing like forever;
}
}
});
The Swing timer fires a an ActionEvent. From the event you can use getSource() to get the source of the event. Cast that source to the swing timer object and use that to turn it off.
To know when to turn it off you need to have a variable count the number of times the swing timer is invoked. When the variable reaches that amount, turn it off.
int elapsedTime = 0;
int timerDelay = 50;
int max = 2000;
public void actionPerformed(ActionEvent ae) {
elapsedTime += timerDelay; // you could use getDelay here but it
// is in milliseconds.
if (elapsedTime >= max) {
Timer s = (Timer)ae.getSource();
s.stop();
}
// rest of code
}
I'm making fast forward button in my Mp3 player. I wrote already code for this, but have problem how to implement timer to jump 5% forward? I mean when I press button timer should jump 5% forward of total long song. This is my fastForward method.
public void FastForward(){
try {
//songTotalLength = fis.available();
fis.skip((long) ((songTotalLength * 0.05)));
} catch (IOException e) {
e.printStackTrace();
}
}
And here is the button method:
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
bar+=5;
}
And this one is for timer:
private void setTime(float t) {
int mili = (int) (t / 1000);
int sec = (mili / 1000) % 60;
int min = (mili / 1000) / 60;
start.set(Calendar.MINUTE, 0);
start.set(Calendar.SECOND, 0);
end.set(Calendar.MINUTE, 0 + min);
end.set(Calendar.SECOND, 0 + sec);
timer = new javax.swing.Timer(1000, new TimerListener());
percent = (float)100/(min*60+sec);
}
You're already redundantly tracking progress in two variables fis and bar. For the sake of good design, use one of those to determine elapsed time rather than using yet another variable for the same purpose.
but have problem how to implement timer to jump 5% forward?
You seem to have mistaken the purpose of a Timer. According to the Timer class documentation, it:
Fires one or more ActionEvents at specified intervals.
So the timer is not meant to keep track of how much time has elapsed. It will simply invoke the actionPerformed(ActionEvent) method of your TimerListener once per second (every 1000 milliseconds) as you have it configured.
For a more complete answer, please post the code for your TimerListener class.
Notes
It seems that your setTime(float) method is meant to be called repeatedly, so this method should not be initializing the timer variable. Rather initialize the timer once and leave it alone to do its job.
I'm assuming you intended the supplied float parameter t to represent microseconds.
The float data type has only 7 digits of precision. This could be fine since you're interested only in minutes and seconds, otherwise float is only good for up to about four months of seconds before losing accuracy.
It seems like you wanted your button click handler to do this (increment bar sooner):
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
bar+=5; // increment bar before checking complete, and before setting progress
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
}
hi guys i am new to java... :(
i just want my button(start) to start a timer but i want to stop the timer automatically with 'if' so for example... when a user enters a time and the timer get's to the timer it stops... so far my coding is like this...
private void startTimerActionPerformed(java.awt.event.ActionEvent evt) {
javax.swing.Timer tm = new javax.swing.Timer(100, new ActionListener()
{
public void actionPerformed (ActionEvent evt) {
AddOneActionPerformed(evt);
}
});
tm.start();
int getTM,getM,getTS,getS,Secs,tenSec,Mins,tenMin;
getTM = Integer.parseInt(enterTenMins.getText());
getM = Integer.parseInt(enterOneMins.getText());
getTS = Integer.parseInt(enterTenSecs.getText());
getS = Integer.parseInt(enterOneSecs.getText());
tenMin = Integer.parseInt(tenMins.getText());
Mins = Integer.parseInt(oneMins.getText());
tenSec = Integer.parseInt(tenSecs.getText());
Secs = Integer.parseInt(oneSecs.getText());
}
and AddOneActionPerformed(evt) is
private void AddOneActionPerformed(java.awt.event.ActionEvent evt) {
int dd,Secs,tenSec,Mins,tenMin;
tenMin = Integer.parseInt(tenMins.getText());
Mins = Integer.parseInt(oneMins.getText());
tenSec = Integer.parseInt(tenSecs.getText());
Secs = Integer.parseInt(oneSecs.getText());
dd= Integer.parseInt(digitValue.getText());
dd= dd+1;
if (dd==10)
dd = 0;
if (Secs == 10)
Secs = 0;
if (dd==0)
Secs=Secs +1;
if (tenSec>=6)
tenSec = 0;
if (Secs==10)
tenSec=tenSec +1;
if (Mins==10)
Mins = 0;
if (tenSec==6)
Mins=Mins+1;
if (tenMin>=6)
tenMin=0;
if (Mins==10)
tenMin=tenMin+1;
String ss = Integer.toString(dd);
digitValue.setText(ss);
String ff = Integer.toString(Secs);
oneSecs.setText(ff);
String gg = Integer.toString(tenSec);
tenSecs.setText(gg);
String hh = Integer.toString(Mins);
oneMins.setText(hh);
String jj = Integer.toString(tenMin);
tenMins.setText(jj);
showDigitActionPerformed(evt);
showOneSecsActionPerformed(evt);
showTenSecsActionPerformed(evt);
showOneMinsActionPerformed(evt);
showTenMinsActionPerformed(evt);
}
You can get the Timer instance from the ActionEvent's getSource() method, and then call stop on it. So,...
// for your Timer's ActionListener
#Override
public void actionPerformed(ActionEvent evt) {
if (someStoppingConditionIsTrue) {
Timer timer = (Timer) evt.getSource();
timer.stop();
} else {
// code to call repeatedly
}
}
Note that you've got two separate issues going on, and should solve them separately. The code above is a way to stop a Timer from within its own ActionListener using some condition. Your other question is how to get user input to allow you to change that condition, and that will involve separate code that is independent of the Timer code above.
Consider in addtion:
Use two JSpinners to for the user's to input minutes and seconds.
Give your class an int totalTime field.
Set this value in your startTimerActionPerformed method.
Have the Timer's ActionListener decrement this value based on measured elapsed time using the differences in calls to System.getSystemTime().
Calculate get the difference between the totalTime and elapsedTime (it will be in milliseconds), say called timeLeft
Calculate your minutes and seconds from timeLeft.
Then display these values in a JLabel using a formatted String, say something like String.format("%02d:%02d", minutes, seconds).
When the timeLeft == 0, that's when you stop your Timer.
I'm trying to make a stopwatch in Java and don't know how to pause and continue my timer. Here is what I have done so far.
startButton.addActionListener(this);
stopButton.addActionListener(this);
pauseButton.addActionListener(this);
public void actionPerformed(ActionEvent e) {
Calendar aCalendar = Calendar.getInstance();
if (e.getSource() == startButton){
start = aCalendar.getTimeInMillis();
startButton.setBackground(Color.GREEN);
stopButton.setBackground(null);
pauseButton.setBackground(null);
} else if (e.getSource() == stopButton) {
stopButton.setBackground(Color.RED);
startButton.setBackground(null);
pauseButton.setBackground(null);
aJLabel.setText("Elapsed time is: " +
(double) (aCalendar.getTimeInMillis() - start) / 1000 );
} else if (e.getSource() == pauseButton) {
pauseButton.setBackground(Color.YELLOW);
stopButton.setBackground(null);
startButton.setBackground(null);
}
}
As you can see, I've only changed the colors for my pause button. I don't really know how to pause the thread by having the user click on the button. All examples I've found of thread.sleep() were with a specific time.
You can use the swing.Timer (not util.Timer) like this:
int interval = 100; // set milliseconds for each loop
Timer timer = new Timer(interval, (evt) -> repeatingProccess());
// create the method repeatingProccess() with your
// code that makes the clock tick
startButton.addActionListener(e -> timer.start());
stopButton.addActionListener( e -> {
timer.stop();
// here refresh your clock with some code...
};
pauseButton.addActionListener(e -> timer.stop());
You write a method called repeatingProccess() and it works in its own thread again and again every interval milliseconds. For a clock that counts seconds you can do this:
int interval = 1000;
int seconds = 0;
public void repeatingProccess() {
seconds++ ;
}
note:
The second will not be exactly 1000 milliseconds but around 1001 because of the time needed to run seconds++ but you can fix that as well by getting System time before and after and substracting the difference from your clock. You should use the Calendar API for this.
I know I am probably way off here, but I am trying to create a timer array so that mytimer[0] mytimer[1], mytimer[2], etc... all fire off at a different interval, with diffrerent events sent to a server. Any ideas? The for loop value of 6 is an organic number for testing purposes only. This number would later be decided base on a setting from the program's xml file.
Timer mytimers[] = new Timer[6];
for(int i = 0;i < 6;i++){
final int mytime = i;
mytimers[i].scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//do action
sendData("Timer " + mytime + " fired");
}
}, 10000, i*1000);
}
Timer mytimers[] = new Timer();
I'm assuming this is the line that doesn't work? You can't initialize an array with an object; initialize it with an array:
Timer mytimers[] = new Timer[6];
Making another guess, you're also not initializing the individual timers:
mytimers[i].scheduleAtFixedRate(new TimerTask() {
At this point mytimers[i] isn't set to anything, so how can you call scheduleAtFixedRate on it? Initialize it first:
mytimers[i] = new Timer();
mytimers[i].scheduleAtFixedRate(new TimerTask() {
EDIT:
Your "IllegalArgumentException: Non-positive period." is because on the first time through the loop, i = 0, so i * 1000 = 0, and the period can't be 0 ("run this event every 0 zero seconds").
Start with i = 1 and it should be fine.
Have you thought about just doing one timer, and the putting all the different events in some sort of (if timeElapsed % timerinterval[1] == 0) and then that way you can simulate the different times by using just one timer. Then you only need an array of integers with the timer interval.
Use this:
Timer mytimers[] = new Timer[6];
for(int i = 0;i < 6;i++){
mytimers[i] = new Timer();
final int mytime = i;
mytimers[i].scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//do action
sendData("Timer " + mytime + " fired");
}
}, 10000, i*1000);
}
The problem is, you are calling the Timer() constructor on an array and never initializing your individual timers. Rather, you should initialize the array as an array and the individual timers as timers.