How to set a delay in Android - java

I'm making a Simon game, while doing it, I created an method that called "Computer" that is activated when the game is starting and after that, every time after the player successes to repeat the sequence.
Here is the code:
private void Computer(){
rounds.setText("Round " + index);
new CountDownTimer(500, 500) {
public void onTick(long millisUntilFinished) {
}
public void onFinish()
{
ResetArray(Player);
//Pushing buttons
Red.setClickable(false);
Blue.setClickable(false);
Green.setClickable(false);
Yellow.setClickable(false);
for (int i = 0; i < index; i++)
{
final Handler handler = new Handler();
final int temp=Game[i];
if (temp == 0)
{
Red.setImageResource(R.drawable.red1);
handler.postDelayed(new Runnable() {
#Override
public void run()
{
StartSound(red);
Red.setImageResource(R.drawable.red);
}
}, 100);
}
if (temp == 1)
{
Green.setImageResource(R.drawable.green1);
handler.postDelayed(new Runnable() {
#Override
public void run() {
StartSound(green);
Green.setImageResource(R.drawable.green);
}
}, 100);
}
if (temp == 2)
{
Blue.setImageResource(R.drawable.blue1);
handler.postDelayed(new Runnable() {
#Override
public void run() {
StartSound(blue);
Blue.setImageResource(R.drawable.blue);
}
}, 100);
}
if (temp == 3)
{
Yellow.setImageResource(R.drawable.yellow1);
handler.postDelayed(new Runnable() {
#Override
public void run() {
StartSound(yellow);
Yellow.setImageResource(R.drawable.yellow);
}
}, 100);
}
}
Red.setClickable(true);
Blue.setClickable(true);
Green.setClickable(true);
Yellow.setClickable(true);
}
}.start();
}
So basically, what iv'e done here is a short delay, of 500 milliseconds, and then it is starting with the self "pushing". This is for create some space between the beginning of the game/starting a new round.
Index- round number.
Game- an array that iv'e created, where there is 50 random numbers which presents the sequence, every round i'm adding one for the index.
Red, Green, Blue, Yellow - References for ImageButtons.
The handler delay is to give some time between the button pressing (which presented by switching the image resource to a same color but brighter, that gives the effect of pressing a button) and un-press it, without it, the changing will be so fast so the player will not be able to see any graphical change.
Basically I need a way to stop the program for a while between each pushing. I need a delayer that will delay the loop every time at it's beginning. The countdowntimer and the Handler are not suitable because the program keeps "running" after the declaring and setting those, the only effect is that the buttons are pushed together but in a delay, which is not what I need.
The result now is that the buttons are seems pushed together and I need to separate their pushing in some way.
Iv'e tried everything, and I could not find nothing.
Thanks,
Ziv.

Using a Handler and postDelayed(...) IS exactly what you need but you're a approaching it wrong.
Basically what you are doing is running through your for loop almost instantly and at each loop you're calling postDelayed(...) with a delay of 100ms.
I'll explain further - suppose index is 4 and it only takes 1ms to go through each run of the for loop. When the 4 runs of the loop are complete you'll have 4 postDelayed events with times of 100ms, 99ms, 98ms & 96ms - - to all intents and purposes, when they trigger they all appear to trigger at once.
One easy way around this with your code is to increase each delay based on the loop count...
int delayTime;
for (int i = 0; i < index; i++)
{
delaytime = (i + 1) * 100;
final Handler handler = new Handler();
final int temp=Game[i];
if (temp == 0)
{
Red.setImageResource(R.drawable.red1);
handler.postDelayed(new Runnable() {
#Override
public void run()
{
StartSound(red);
Red.setImageResource(R.drawable.red);
}
}, delayTime); // NOTE USING delayTime AS THE DELAY
}
//
// REPEAT THE ABOVE CODE FOR BLUE, GREEN & YELLOW HANDLER DELAYS
}
In other words when i=0, delayTime will be 100ms, when i=1, delayTime is 200ms etc etc

probably you want to sleep the thread for 500 milliseconds, then you can do this to slept your thread.
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Related

Timer doesn't execute functions within a method consecutively Java

I'm trying to implement a functionality within a game that I've made where if you press a button, the car will auto complete a lap of the track without any user input.
To do this, I've created functions for each direction of movement.
I needed to create a delay between each function call, otherwise it'll complete the lap the instant I press the button to initialise it. I've added the following:
public void driveCar()
{
Timer t = new Timer(1000 * 1, new ActionListener() {
public void actionPerformed(ActionEvent e) {
move(MOVE_RIGHT);
move(MOVE_DOWN);
}
});
t.start();
}
If I only have the MOVE_RIGHT, it'll act as a loop and continuously run this method and move one space to the right every second however, I'm trying to make it so that it'll move one step to the right once, and then one step downwards. Currently, it's just moving diagonally every tick.
How can I implement a solution that carries out each call as if it's a list of instructions?
If you want the action of the timer to alternately move right or move down on each tick, you need a field tracking the progress:
Timer t = new Timer(1000 * 1, new ActionListener() {
private boolean moveRight = true;
public void actionPerformed(ActionEvent e) {
if (moveRight)
move(MOVE_RIGHT);
else
move(MOVE_DOWN);
moveRight = ! moveRight;
}
});
If you have more than two different actions, you can use a step counter:
Timer t = new Timer(1000 * 1, new ActionListener() {
private int step = 0;
public void actionPerformed(ActionEvent e) {
switch (step) {
case 0:
move(MOVE_RIGHT);
break;
case 1:
move(MOVE_DOWN);
break;
case 2:
move(MOVE_UP);
break;
}
step = (step + 1) % 3;
}
});
UPDATE: If you want to walk a specific path, use an array:
final int[] path = { MOVE_RIGHT, MOVE_DOWN, MOVE_UP, MOVE_UP, MOVE_LEFT, MOVE_DOWN };
Timer t = new Timer(1000 * 1, new ActionListener() {
private int step = 0;
public void actionPerformed(ActionEvent e) {
move(path[step]);
step = (step + 1) % path.length;
}
});

Thread not behaving as expected after rewrite

I'm writing an android app to measure display lag on tvs using the mirror function on the video out. After many revisions, my code got too complex for its own good, so I scraped it and did a rewrite. My issue is that it is not behaving as expected. The square is not blinking, and the time is 0.0 and the rating is excellent. i have tested changing the ui via the thread by making the square turn different colors, that worked fine. Can someone tell me what the issue is and how to fix it? The way the app works is that you hook the device to a tv and it mirrors the display. then it changes the color of a square in the app and dose a time stamp, then it wait till the camera detects a change then dose another time stamp. using both time stamps you can figure out the delay of the tv. I have it in a loop because the camera only captures at 15ish fps, so I need to run the test multiple times to get an accurate result. The issue is that it always shows up as 0.0ms, that is an impossible number because the lag on most consumer tvs is 9ms. I get the RGB values from each camera frame.
class lagTestThread extends Thread {
#Override
public void run () {
long lagStartTime;
long lagEndTime;
long tempResult;
final double rating;
int x;
long testResult = 0;
int cnt;
for (cnt = 0; cnt >= 100; cnt++){
runOnUiThread(new Runnable() {
#Override
public void run() {
lagSquare.setBackgroundColor(Color.rgb(000, 000, 000));
}
});
while (redVal >= 10.0 && blueVal >= 10.0 && greenVal >= 10.0) {
x = 0;
}
redVal = 0;
blueVal = 0;
greenVal = 0;
lagStartTime = System.nanoTime(); //start lagTimer start
runOnUiThread(new Runnable() {
#Override
public void run() {
lagSquare.setBackgroundColor(Color.rgb(255, 255, 255));
}
});
while (redVal <= 100.0 && blueVal <= 100.0 && greenVal <= 100.0) {
x = 0;
}
lagEndTime = System.nanoTime(); //start lagTimer end
runOnUiThread(new Runnable() {
#Override
public void run() {
lagSquare.setBackgroundColor(Color.rgb(000, 000, 000));
}
});
tempResult = (lagEndTime - lagStartTime);
if (tempResult <= testResult && tempResult != 0) {
testResult = tempResult;
}
}
rating = ((double) testResult) / 1000000.0;
final String finalResultString = String.valueOf(rating);
runOnUiThread(new Runnable() {
#Override
public void run() {
lagTime.setText(finalResultString);
if (rating <= 17.0) {
lagRating.setText("Excellent");
} else if (rating <= 34.0) {
lagRating.setText("Great");
} else if (rating <= 51.0) {
lagRating.setText("Average");
} else {
lagRating.setText("Bad");
}
}
});
}
}
I call it like this
public void startTest(View view) {
lagTestThread lagTest = new lagTestThread();
lagTest.start();
}
redVal, blueVal, greenVal declaration
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
double[] rgb = inputFrame.rgba().get(100, 100);
redVal = rgb[0];
blueVal = rgb[2];
greenVal = rgb[1];
Log.i("", "red:" + rgb[0] + " green:" + rgb[1] + " blue:" + rgb[2]);
return rgbMat;
}
The runOnUiThread() causes the Runnable to be posted to the UI thread, at which point the function returns immediately. The Runnable executes at some later time.
Your code is posting events to the UI thread and checking the system time, which means you're calculating how long it takes to post events to the UI thread, not how long it takes them to run. Also, because all the events are queued up behind one another, it's likely they will all execute in the same frame, so you will only see the result of the last setBackgroundColor() call.
If you really want to divorce your display and timing code from the UI thread, you should consider doing this with a SurfaceView, which can be updated independently of the UI thread. (The down side of SurfaceView is that it's a lot more complicated to work with than a custom View.)

Graph plotter with timer in java

I'm working on a grapher that gets an expression like x^2 + t from the user and then will ask the user for range of x and t .
t in here is the timer variable.
so in x^2 + t the user for example will choose the -10 to 10 for x and 1 to 5 for t . now by clicking the draw button in GUI program the code will start plotting the expression from minimum t (1 in here) and after each second(or any time period) will increase the t value by one and draw the expression with new t (2 ,3 until it reaches the maximum range).
how can make the event handler to do this? I have found a way to draw multiple graphs but I can't make a delay so the minimum to maximum .
I know I should use timer but I don't know how to use in this part of the code
the Link for the whole code
this is the part of code in plotter class that should be changed :
// Grapher
drawButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
String testSpring = null;
String tVarString = null;
for (int i = 0; i < 5; i++) {
testSpring = inputExpression;
tVarString = String.valueOf(i);
testSpring = testSpring.replaceAll("t", tVarString);
Equation equation = new Equation(testSpring);
graph.addEquation(equation);
}
}
catch (EquationSyntaxException e) {
e.printStackTrace();
}
}
});
This is the picture of the program :
my priority is to make the program run just by clicking draw button
but It would be better if this timer could be influence JSlider
so the min and max of t would be min and max of Jslider and by clicking draw it would start drawing by every time slider knob would point at a value for t
Take a look at How to use Swing Timers
This will allow you to setup a callback at a regular interval, which is executed from within the context of the EDT, making it safe to update the UI from within
public void actionPerformed(ActionEvent arg0) {
Timer timer = new Timer(1000, new ActionListener() {
private int iteration;
#Override
public void adtionPerformed(ActionEvent evt) {
try {
String testSpring = null;
String tVarString = null;
testSpring = inputExpression;
tVarString = String.valueOf(iteration);
testSpring = testSpring.replaceAll("t", tVarString);
Equation equation = new Equation(testSpring);
graph.addEquation(equation);
} catch (EquationSyntaxException e) {
e.printStackTrace();
} finally {
iteration++
if (iteration > 4) {
((Timer)evt.getSource()).stop();
}
}
}
});
timer.start();
}
});

How do you change label text in java after a timer ticks a second passed?

I have a timer with a delay of 5 seconds. I am trying to change the label named lblTimer after a second passes to act as a countdown. I am having issues with it as currently it only works at 5 seconds. Do you have any suggestionsuggestions?
protected void Addition() {
//addition function
final int delay = 5000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
#SuppressWarnings("unused")
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
frame.getContentPane().setBackground(Color.red);
}
};
new Timer(delay, taskPerformer).start();
Random RandomNumber = new Random();
int number1 = RandomNumber.nextInt(12);
int number2 = RandomNumber.nextInt(12);
int number3 = RandomNumber.nextInt(12);
lblAnswer.setText("");
lblFirstNumber.setText(""+ number1);
lblfunction1.setText("+");
lblsecondNumber.setText(""+number2);
lblfunction2.setText("+");
lblthirdnumber.setText(""+number3);
lblequals.setText("=");
answer = number1+number2+number3;
if(delay <= 1000){
lblTimer.setText("1");
}
else if(delay == 2000){
lblTimer.setText("2");
}
else if(delay == 3000){
lblTimer.setText("3");
}
else if(delay == 4000){
lblTimer.setText("4");
}
else if (delay == 5000){
lblTimer.setText("5");
}
}
The answer to your question, that I assume is "why does this not work?", is that at no point do you recheck the elapsed time. The variable delay is always set at 5000, and never updated, also.
The stupid-ass solution:
lblTimer.setText("5");
Thread.sleep(1000)
lblTimer.setText("4");
Thread.sleep(1000)
lblTimer.setText("3");
Thread.sleep(1000)
lblTimer.setText("2");
Thread.sleep(1000)
lblTimer.setText("1");
Thread.sleep(1000)
lblTimer.setText("0");
Don't really do this, unless you need to satisfy your sick fetishes.
The four-liner
The same as above. Don't do this.
for (int i = secondsToWait; i >= 0; i--) {
lblTimer.setText(i + "");
Thread.sleep(1000);
}
The acceptable solution:
Use a Timer to schedule a task to be executed after a given period of time. You can use timers to also fire the same task multiple times at a given interval.
Timer timer = new Timer();
int secondsToWait = 5;
TimerTask task = new TimerTask() {
#Override
public void run() {
secondsToWait--;
lblTimer.setText(secondsToWait + "");
if (secondsToWait == 0) {
timer.cancel();
timer.purge();
}
}
};
lblTimer.setText(secondsToWait + "");
timer.scheduleAtFixedRate(task, 1000, 1000);
The best solution:
Instead of a timer, use a ScheduledExecutorService. This is better because of the way ScheduledExecutorService works with threads as opposed to Timer. Google it.
ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
int secondsToWait = 5;
Runnable task = new Runnable() {
#Override
public void run() {
secondsToWait--;
lblTimer.setText(secondsToWait + "");
if (secondsToWait == 0) {
exec.shutdown();
}
}
};
lblTimer.setText(secondsToWait + "");
exec.scheduleAtFixedRate(task, 1, 1, TimeUnit.SECONDS);
EDIT: As Stefan pointed out, for swing GUI applications a swing Timer would be the best pick.
It should look something like this:
1) create Timer
2) create TimerTask and implement run method (updating your count variable and check if counter is zero. if it is zero, stop the timer)
3) schedule the task to run every second
int count = [INITVALUE];
...
public void startMethod() {
final Timer timer = new Timer();
timer.shedule(new TimerTask() {
#Override
public void run() {
count--;
lblTimer.setText(count+"");
if (count == 0) {
timer.cancel();
timer.purge();
}
}
},1000);
}
Thumbs Up #Olavi Mustanoja your answer revealed an option I have never tried before now.
As he lastly suggested on his edit the javax.swing.Timer comes in very handy if you're work with GUI.
import javax.swing.Timer;
private int secondsToWait = 5000; //Time in milliseconds
private Timer timer;
....
//The following section should be inside a method member
timer = new Timer(secondsToWait, e -> {
if(secondsToWait == 0)
timer.stop();//Stop if secondsToWait is already zero
lblTimer.setText((secondsToWait/1000) + ""); //Update the label with the current sec
timer.setDelay(secondsToWait);
secondsToWait -= 1000; //Reduce time by 1sec each time
});
timer.start();
...

For loop display numbers in label [duplicate]

The idea of my program is to select one name from a list that saved before in other JFrame. I'd like to print in the label all names one after the other with small delay between them, and after that stop at one of them. The problem is that lbl.setText("String"); doesn't work if there is more than one setText code.
Here is the part of my code :
public void actionPerformed(ActionEvent e)
{
if (RandomNames.size != 0)
{
for (int i = 0; i < 30; i++)
{
int rand = (int)(Math.random() * RandomNames.size);
stars.setText(RandomNames.list.get(rand));
try
{
Thread.sleep(100);
}
catch (InterruptedException err)
{
err.printStackTrace();
}
}
int rand2 = (int)(Math.random() * RandomNames.size);
stars.setText(RandomNames.list.get(rand2));
RandomNames.list.remove(rand2);
RandomNames.size = RandomNames.list.size();
}
if (RandomNames.list.size() == 0)
{
last.setText("\u062A\u0645 \u0638\u0647\u0648\u0631 \u062C\u0645\u064A\u0639 \u0627\u0644\u0623\u0633\u0645\u0627\u0621 \u0627\u0644\u062A\u064A \u0641\u064A \u0627\u0644\u0642\u0627\u0626\u0645\u0629 !");
}
}
Don't use a loop or Thread.sleep. Just use a javax.swing.Timer. The following will cause 30 iterations occurring every 1000 milliseconds. You can adjust the code in the actionPerformed accordingly to what you wish to happen every so many milliseconds.
int count = 0;
...
Timer timer = new Timer(1000, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
if (count == 30) {
((Timer)e.getSource()).stop();
} else {
int rand = (int) (Math.random()* RandomNames.size);
stars.setText(RandomNames.list.get(rand));
count++;
}
}
});
timer.start();
If you want you can just set up the Timer in the constructor, and start() it in the actionPerformed of another button's listener.
See more at How to use Swing Timers

Categories

Resources