I am trying to simulate a timer. So upon clicking button in the JFrame form, I want the timer to countdown from say 10 to 0. I want it to be exactly 10s. I don't want to find elapsed time of any codes as whatever codes I have found so far give elapsed time. For example using System.nanoTimer().
I tried doing this:
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:timer
long startTime = System.nanoTime();
// ... the code being measured ...
long targetTime=startTime+10000;
while(System.nanoTime()<targetTime)
{
JOptionPane.showMessageDialog(this,targetTime-System.nanoTime());
}
JOptionPane.showMessageDialog(this,"time's up");
}
But of course it hardly shows the time left once or twice. Can someone help me with the logic?
10000 nanosec's is 10 miliseconds and that is is 1/100 of one second.
Use:
System.currentTimeMilis
instead
Related
I am relatively new to programming, and to help myself I am making a personal project.
I am using Javafx to build drum machine, which allowing the user to program a sequence of beats.
I have constructed sets of rows which each will function as a programmable beat sequencer for each corresponding instrument, with each row consisting of 16 buttons. if that button is pressed, the button is activated, and it will produce the instrument's sound when the loop passes through that point.
for reference this piece of kit is similar to what i wish to construct :
https://images-na.ssl-images-amazon.com/images/I/81RctDCP38L._AC_SL1500_.jpg
Each button is assigned to a hashmap; the Key is an integer from 0-16, while the value is the button's characteristics itself.
The drum machine loops after 4 bars/ 16 buttons.
To trigger the event and to cause the instrument to play, the time (as a fraction of all buttons/16) will match the key of a button. once this occurs, the sound plays. the method to do this is below:
public void beatState(Button button, String filename) {
EventHandler handler = new EventHandler() {
#Override
public void handle(Event event) {
soundGeneration sound = new soundGeneration(filename);
// if the corresponding buttons key (on a range of 0-16) matches the time as a fraction (0-16)
// and if the button text is on (activated by clicking the pad)
if (button.equals(map.get(time.timeToFraction())) & button.getText().equals("On")) {
// plays the file
sound.play();
// when duration of animation is set lower the filename prints more frequently
// or sometimes not printed/sound played when the duration is higher
System.out.println(filename);
}
}
};
// as i increase the duration of the animation , the program becomes both slower but returns
// both the sound file and prints the filename more often
Timeline animationButton = new Timeline(new KeyFrame(Duration.millis(100), handler));
animationButton.setCycleCount(Timeline.INDEFINITE);
animationButton.play();
}
I'll next provide the time element:
public Integer timeToFraction(){
labelFormat();
new AnimationTimer() {
#Override
public void handle(long now) {
// time elapsed since program execution
double elapsedMillis = (System.currentTimeMillis() - startTime);
// converts to long
// multiplies the value to privide a fraction
long numerator = (long) ((elapsedMillis/1000)*8.33);
// value below denominates the time it takes to travel 4 beats at 125 beats per minute
double denominator = 1.92;
// converts below to show as a fraction
long denominatorToBeat =(long) Math.round(denominator * 8.3);
// if the elapsed time raises over 16
// resets numerator
if (numerator> denominatorToBeat) {
startTime = System.currentTimeMillis();
elapsedMillis = (System.currentTimeMillis() - startTime);
}
// converts from long to to allow for hashmap matching against button position
fractionTime = (int) numerator;
}
}.start();
return fractionTime;
}
When the values match up the beat plays, achieving my aim; however, it plays multiple times, and irregular in relation to the beat.
I assume that the animation timer repeat value in milliseconds is what causes this; I decrease it, there are more unwanted repeated sounds. I increase it and notes sometimes are not counted due to the animation passing over the value before it triggers.
I want the code to trigger the sound file when it passes over the button, more specifically when the Integer value of the hashmap the button corresponds to matches the time fraction.
I have spent hours researching and reading the documentation and for an easy problem it is becoming incredibly difficult to work around. Given that this project is seen in a multitude of portfolios and music development software i am sure there is a simple fix to my issue.
Thanks for taking the time.
Your approach in general is wrong, as you are abusing animation timers to do something not related to the GUI. You have to decouple the logic from the GUI.
I.e. The object which controls the timing and playing the sounds should have nothing to do with the buttons or any GUI. It should have some methods to set / clear a sound at particular interval, and then expose its state using properties, e.g. an ObjectProperty with some class describing the current tones being played.
The buttons should call the methods to set / clear tones, and you can add a change listener to the ObjectProperty to update the buttons appearance based on the state.
I am thinking about making an android app to support a game of mine, and I can't find info on how to do it. Here is an app explanation:
The app should have two timers (both set for x minutes). When first player starts his turn (by a button click) his time starts running out. when first player makes his move, he should click his time to stop it, and player two starts his turn.
NOW, the problem I can't find a solution for - When player one takes his turn, time that he loses should pass to the other player's timer.
Example: Both players start with a 5 minute timer. If player one takes 30 second for his turn, his time should go down to 04:30, at which time he clicked on his timer. During that time, for each second he lost, the other player gained time on his timer, so at the beginning of his turn, his time is 05:30. The time goes back and forth, and the player whose timer runs out loses the game.
Any idea how to do this?
I am still stuck to the idea on how to make it, so I have no code to share.
Thank you all for your answers, and effort in helping me, if you have a question I haven't covered, I will gladly answer it.
First, you will need to instantiate class of CountDownTimer everytime you click on button.
For reference check here: https://developer.android.com/reference/android/os/CountDownTimer.html
You have two parameters long millisInFuture, long countDownInterval
Before you start, you will need to create two global variables one for first player, and one for second player like this:
long firstPlayerRemainingTime = 5 * 60 * 1000; // start time 5 minutes
long secondPlayerRemainingTime = 5 * 60 * 1000;
long limitedTime = 30 * 1000; // 30 seconds
CountDownTimer mCountDownTimer;
Now we have came to the most important part and that is logic inside onClickListener method
I don't know if there are two buttons or one, but I will go with two buttons:
btnFirstPlayer.setTag(1); // start timer
btnFirstPlayer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (btnFirstPlayer.getTag() == 1) {
startTimer();
} else {
stopTimer();
}
});
private void startTimer() {
long startTime = firstPlayerRemainingTime;
btnFirstPlayer.setTag(2); // stop timer
btnFirstPlayer.setText("Stop");
mCountDownTimer = new CountDownTimer(firstPlayerRemainingTime, 1000) {
public void onTick(long millisUntilFinished) {
firstPlayerRemainingTime = millisUntilFinished;
tvPlayerOneTimer.setText("" + firstPlayerRemainingTime / 1000)
// Here you would like to check if 30 seconds has passed
if ((startTime / 1000) - (limitedTime / 1000)
== (firstPlayerRemainingTime / 1000)) {
stopTimer();
}
// Here you would like to increase the time of the second player
secondPlayerRemainingTime = ++1000;
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
}
}
private void stopTimer() {
btnFirstPlayer.setTag(1);
btnFirstPlayer.setText("Start");
mCountDownTimer.cancel();
// I guess here starts second player move
}
The same logic would go for second player. Let me know if this helped you or if I need to explain anything.
Recently, I've been getting into Java Game programming. I have learned Java before, but this is my first time with Graphics, Game Loops etc.
I followed this tutorial for a Game Loop, and it's working pretty well.
There is nothing wrong with it, but I just can't figure out why I am thread.sleeping the code, and whats the point of it.
If anyone could explain what start, elapsed and running do, and why I am doing thread.sleep(wait) then I would be super appreciative!
GAME LOOP (Remember, it works, I just don't know why):
while (running) {
start = System.nanoTime();
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed / 1000000;
if (wait < 0) {
wait = 5;
}
try {
Thread.sleep(wait);
} catch (Exception e) {
Game.logger.log("ERROR! Printing Stacktrace...");
e.printStackTrace();
}
}
}
Well, running is a flag that can be set to false to terminate the game.
start and elapsed are used to measure the time one round in the loop took. You are waiting to not make the game run too fast. If you are moving elements with a set speed, then having the game loop run too fast makes them also move too fast. That can lead to a bad user experience, since the user might not be fast enough to play the game.
Additionally, any animation doesn't run smooth anymore without the waiting. It will speed up and slow down depending on how fast your code executes.
Just continue with the tutorial, and when are at the point where you make something move, remove the waiting and see what happens.
EDIT
The code makes a round in the loop take about targetTime. It's unit is milliseconds. So to calculate the frame rate, just divide 1000 / targetTime.
start is the time before the game logic runs. elapsed is the amount of time that it takes for the game logic to run. running is a boolean (true/false) variable that determines whether the game should continue. Thread.sleep(wait) is a method that delays for a certain amount of time.
The goal is to keep the amount of time between frames roughly constant by delaying, so that the animations don't run faster or slower depending on how fast your computer processor is running.
It appears the code aims to be executed targetTime seconds. So you count how much time has already passed (elapsed), and then calculate how much to wait (divide it to get your remaining time in miliseconds, required for methon sleep(wait)).
One purpose of such waiting is often forcing some time between repainting to the screen.
To get your FPS, one way would be to slightly change your code:
long prevStart = 0; //just initialize. First FPS is of course wrong, next get fine.
double FPS = 0;
while (running) {
start = System.nanoTime();
FPS = 1 / double(start - prevStart);
prevStart = start;
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed / 1000000;
if (wait < 0) {
wait = 5;
}
try {
Thread.sleep(wait);
} catch (Exception e) {
Game.logger.log("ERROR! Printing Stacktrace...");
e.printStackTrace();
}
}
Below I have a Runnable "updater" ...and an OnClick function that uses Handler.PostDelayed function to run the runnable after a delay...
After a little editing, cutting of useless parts here are the functions:
(passtog = Toggle Button)
final Runnable updater = new Runnable() {
#Override
public void run() {
if (passTog.isChecked()) {
now = System.currentTimeMillis();
time = now - init;
if (time > 5000) {
Toast.makeText(getApplicationContext(), "WAKE UP !",
Toast.LENGTH_SHORT).show();
}
handler.postDelayed(this, 25);
}
}
};
passTog.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
init = System.currentTimeMillis();
flag = true;
handler.postDelayed(updater,
(new Random().nextInt(4000) + 3000));
}
});
}
Explaination
Basically, The user toggles the Toggle button. Now it's on: The runnable can run completely (Everything is in the if block).
If the user doesn't press the button again, and switches it off The app sends a Toast "Wake Up!" ..It runs and checks every 25 millisecs to update the time...
Pretty straightforward... Yet I'm having a problem.
Before the program actually gets to the runnable, I absolutely NEED there to be a minimum time delay of 3 seconds + Some Random value ... So it varies between 3 sec - 7 sec. It SHOULD vary between 3-7 , but it doesn't.
When I run it: The problem
I notice that the first time, it works great... I get atleast a 3 sec delay + a random value= Perfect
The second time, that is after the switch goes on ->off-> on : Now It acts like it doesn't see the +3000 ...and just the ~randInt(4000) function... So it may give 0 sec or it may give 4 sec delay...
In all my experience, I've never really come across this.. I've rewritten the entire code, My other apps use this function in exactly the same sytax and seem to do pretty great.. Why is this creating a problem ? Could the Toast's time possibly be causing a problem..
How to solve this ?
(I'm open to other methods, preferably quick to implement. I want a minimum 3 sec delay which I'm not getting for some reason... I need the UI to be responsive though So no thread sleeping.)
You probably should call Handler.removeCallbacksAndMessages(null) when the switch goes off.
I want to create an incrementing second timer like a stopwatch.
So I want to be able to display the seconds and minutes incrementing in the format 00:01...
Google only brings up 24 hour clock examples, I was wondering could anyone get me started with an example or tutorial of what I want to do?
Edit:
Here is what I have using the Chronometer in Android so far
In onCreate()
secondsT = 0;
elapsedTimeBeforePause = 0;
stopWatch.start();
startTime = SystemClock.elapsedRealtime();
stopWatch.setBase(elapsedTimeBeforePause);
stopWatch.setOnChronometerTickListener(new OnChronometerTickListener(){
#Override
public void onChronometerTick(Chronometer arg0) {
//countUp is a long declared earlier
secondsT = (SystemClock.elapsedRealtime() - arg0.getBase()) / 1000;
String asText = (secondsT / 60) + ":" + (secondsT % 60);
//textGoesHere is a TextView
((TextView)findViewById(R.id.time)).setText(asText);
}
});
In onDestroy()
#Override
public void onDestroy() {
inCall = false;
elapsedTimeBeforePause = SystemClock.elapsedRealtime() - stopWatch.getBase();
super.onDestroy();
}
The above compiles and runs but the TextView never increments, it always stays at 0, can anyone see why?
I'm assuming you aren't aware of the Android Chronometer - it already has a basic stopwatch function. You need to work with its peculiarities a bit, but it's not hard to get it to do what you want once you understand how it works.
There are a few ways that time is calculated on the phone, but the two main ones are:
The "real time", such as right now according to my computer clock, it is 11:23am in England. However, this can change if my computer contacts a time server and is told it has the wrong time, or if I were travelling with a laptop and crossed a timezone boundary. Using this would wreak havoc with your stopwatch as the measured time could change at any time.
The "elapsed time since boot", which is the number of milliseconds since the phone was switched on. This number doesn't bear any relation to the real time it is, but it will behave in a perfectly predictable manner. This is what the Android Chronometer uses.
The Chronometer is essentially a 'count up' timer, comparing the current SystemClock.elapsedRealtime() against the elapsedRealtime() that was set fot its base time. The difference between the two, divided by 1000, is the number of seconds since the timer was started. However, if you stop the timer and then start it again, you will get a counter-intuitive result - the timer will show the elapsed time as if it had never stopped. This is because you need to adjust its base time to take into consideration the time it was stopped. This is simple to do:
// When you're stopping the stopwatch, use this
// This is the number of milliseconds the timer was running for
elapsedTimeBeforePause = SystemClock.elapsedRealtime() - timer.getBase();
// When you're starting it again:
timer.setBase(SystemClock.elapsedRealtime() - elapsedTimeBeforePause);
Edit: Here is the full code for a basic stopwatch, which displays your time in a TextView rather than the Chronometer widget declared in your XML file.
public class TestProject extends Activity {
TextView textGoesHere;
long startTime;
long countUp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Chronometer stopWatch = (Chronometer) findViewById(R.id.chrono);
startTime = SystemClock.elapsedRealtime();
textGoesHere = (TextView) findViewById(R.id.textGoesHere);
stopWatch.setOnChronometerTickListener(new OnChronometerTickListener(){
#Override
public void onChronometerTick(Chronometer arg0) {
countUp = (SystemClock.elapsedRealtime() - arg0.getBase()) / 1000;
String asText = (countUp / 60) + ":" + (countUp % 60);
textGoesHere.setText(asText);
}
});
stopWatch.start();
}
}
In your main.xml you need to have this
<Chronometer android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/chrono"
android:visibility="gone"/>
There's undoubtedly a way to get the Chronometer to work without declaring it in the XML file, but the constructor Chronometer stopwatch = new Chronometer(this); didn't work properly.
The above code displays the elapsed time in a very basic way. For example, if only 5 seconds have gone by, it will show 0:5 rather than the 0:05 you probably want. Fixing that is not hard to do, but I'll leave that for you to work out! :)
How about this one Digital Clock.
But basically you should be able to find many java implementations by googling for keywords like java, stopwatch, digital clock, ...
You could take a look at Stopwatch Applet and modify as needed (Oops no source with this one)