I am trying change the image LayoutX and LayoutY positions ever 1 second. But I cant find any (timer) method suitable for this. I am looking for something similar to the JavaScript "setInterval" that simply lets me create a "timer cycle" using Java or JavaFX.
Any advice are widely appriciated!
With java.util.Timer you can schedule such a task.
The method timer.schedule() executes a task only ones. To repeat your task
use the method timer.scheduleAtFixedRate().
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
System.out.println("hello");
}
}, 1000, 1000);
The second parameter of scheduleAtFixedRate() is the delay before the first execution in milliseconds and the last parameter is the interval between the tasks being executed in milliseconds.
You can use a Timeline with INDEFINITE cycle count for this purpose.
Example:
Timeline tl = new Timeline(new KeyFrame(Duration.seconds(1), evt -> {
// toggle image postion
imageView.setLayoutX(200 - imageView.getLayoutX());
imageView.setLayoutY(200 - imageView.getLayoutY());
}));
tl.setCycleCount(Animation.INDEFINITE);
tl.play();
This guaranties the event handler runs on the JavaFX application thread.
Related
Currently, I am making a Java program for graph visualization Prim's algorithm in finding minimum spanning tree.
Here is the image of my program's output
while(condition){
//Find the min vertex and min edges
Vertex vertex = findMinVertex();
Edge[] edges = findMinEdges();
//Then, for each vertex and edges I found, I will change the color of
//them and pause the program for 3 seconds, so user can see how
//algorithm works.
repaintAndPause(3000);
}
.
.
private void repaintAndPause(int time){
long start = System.currentTimeMillis();
long end = start + speed;
//Here is the timer for repainting.
Timer timer = new Timer(speed, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e){
GraphPanel.this.repaint();
}
});
timer.setRepeats(false);
timer.setDelay(0);
timer.start();
//And here is for pausing the program, a while loop without any commands.
while(System.currentTimeMillis() < end){}
}
However, I don't know why but the program doesn't work. Yes, there are the pauses of program but, all the edges and vertices are just changed the color at the end of program. They aren't changed every 3 seconds.
Could someone please tell me where I did wrong?
Thank you and hope you have a nice day!
Could someone please tell me where I did wrong?
Yes. You are putting a busy-loop in the Event Dispatching Thread.
while(System.currentTimeMillis() < end){}
You code reads:
do some calculation (busy)
when done, post a "repaint" message, to redraw the panel when not busy
continue being very busy doing nothing for 3 seconds
continue being busy by repeating steps 1 through 4.
The Event Dispatching Thread never finishes processing the first "event" until the end of the algorithm, after the while (condition) loop finally finishes.
You want:
Timer timer = new Timer(speed, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
/* Code to perform one step of Prim's algorithm here */
/* Change edge/vertex colour for step */
/* Call timer.stop(), once done */
GraphPanel.this.repaint();
}
});
timer.setRepeats(true);
timer.setDelay(3000);
timer.start();
On every tick of the timer (once every 3 seconds), one step of the algorithm is performed.
Note this means that each step of the algorithm must run with any partial results stored into class members, so the the next step will be able to retrieve all the information it needs to continue. Stack variables can only be used inside one step; they cannot be used to hold inter-step values.
You could rework the algorithm to use a SwingWorker to run the calculation in its own background thread, and publish intermediate results when computed. The EDT could then repaint as intermediate results are produced. With a Thread#sleep() call, this background thread could delay production of intermediate results to once per 3 seconds.
Alternately, you could run the algorithm, and store multiple copies of the output, once for each 'step'. Then your Panel timer could simply show the output of the next step.
I have a simple java snake game. I'm trying to test what happens when I press a lot of keys in a short interval.
Snake is my frame and Board is the JPanel where everything happens.
boolean stop=false;
Snake snake= new Snake();
KeyEvent key_right = new KeyEvent(snake.board, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_RIGHT,'Z');
KeyEvent key_up = new KeyEvent(snake.board, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_UP,'Z');
KeyEvent key_down = new KeyEvent(snake.board, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_DOWN,'Z');
KeyEvent key_left = new KeyEvent(snake.board, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_LEFT,'Z');
KeyEvent vect[]={key_right,key_down,key_left,key_up};
int i=0,nr=0;
Timer timer = new Timer();
#Test
public void StresTaste() {
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if(!stop){
snake.board.getKeyListeners()[0].keyPressed(vect[i]);
System.out.println(nr);
i++;nr++;
if(i==3) i=0;
if(nr==200){stop=true;}
}
}
}, 1, 1);
}
I create an array of keyEvents and loop over it using the i variable. I pass them to the keyListener of the JPanel.
Everything works fine.. but it stops at something over one hundred...not the same value everytime.
Please help. Is this even possible to implement?
A timer is a daemon thread, i.e. when one of them is around, that won't stop the VM from stopping.
So what happens is that you start the tests, create the timer and then stop the VM (because there are no more JUnit tests). The timer gets to process a couple of times but eventually, the termination of the VM kills it.
The solution is to add a lock to your code:
final Object lock = new Object();
timer.scheduleAtFixedRate(new TimerTask() { ...
if(stop) { synchronized(lock) { lock.notify(); }} // let test know that we're done
});
synchronized(lock) { lock.wait(); } // wait for timer to finish
That said, it's probably futile to test how many keypresses your code can process per second. The hardware, OS and human hands put a limit of about 215 words per minute.
Most often, the code doesn't care how fast it's being called but how often (memory leaks). So you can probably change your code to just loop over the key sequence and simply call snake.board.getKeyListeners() without a background thread (which, incidentally, will also give you hundreds of thousands of invocations per second).
I am trying to set a timer to randomly set the frame in the screen, but then, depending on the boolean, set it back to normal. I have already tried .cancel() but it doesn't work. How could I stop this timer?:
if(e.getSource()==impossible){
impossiblity=!impossiblity;
System.out.println(impossiblity);
if(!impossiblity){
new Timer().schedule(new TimerTask() {
public void run() {
int randWidth=(int)((dim.width-gameFrame.getSize().width) * Math.random());
int randHeight=(int)((dim.height-gameFrame.getSize().height) * Math.random());
gameFrame.setLocation(randWidth, randHeight);//sets location to center
}
}, 1000, 1000);
} else gameFrame.setLocation(dim.width/2-gameFrame.getSize().width/2, 0);//sets Location to center of screen
}
right now it does set the gameframe back to normal but then goes right back to randomizing
In general trying to cancel timers or other threads from outside the thread is a bad idea and leads to all sorts of problems.
Your best bet is to set some sort of flag or counter that the TimerTask checks when it comes to run.
I have a Java Swing timer which updates a label every second. After starting the timer, the label is updated every second and everything works well.
Then after a random time interval, which changes from execution to execution, the label stops being updated. I've put a breakpoint in the timer update code and it no longer gets triggered.
I've also put log statements in all the places where I would normally stop the timer, but none of those places are called.
What could be the problem?
EDIT: Here is the sample of the code
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent arg0) {
secondsRemaining--;
System.out.println("Seconds remaining:" + secondsRemaining);
//update the progressbar
double initialLength = currentSettings.getLength()*60;
double progress = (initialLength - secondsRemaining)/initialLength ;
progressBarTime.setProgress(progress);
//update the progress label
progressPercentage.setText(((int)(progress * 100)) + "%");
if (secondsRemaining >= 0) {
updateTimeRemaining(secondsToString(secondsRemaining));
} else {
System.out.println(">0 seconds TIMER STOPPED with the number of seconds = " + secondsRemaining);
treatmentTimer.stop();
// set the status to Finished
currentState = State.FINISHED;
}
}
}
And the timer initialization:
tTimer = new Timer(1000, actionListener);
tTimer.start();
What's strange is that the program works fine on a PC with JRE 7u7 installed, i.e. the timer updates the label successfully, but I've tried on two PCs with 7u10 and this timer stopping issue happens on both.
Exception might be thrown, use try catch or Use UncaughtExceptionHandler to trace.
So I think I solved the problem. The garbage collector was removing the timer instance, for some unknown reason. I put a
System.out.println("message");
Inside the actionlistener of the timer, so that it would not be garbage collected.
I want to create a simple clock using Java. The code is so simple that I will give an example:
for(int i=0;i<=60;i++)
jLabel11.setText( Integer.toString(i) );
The problem is while I'm running my program the result didn't show each update in sequence.
It show only the 60 digit immediately, without showing the change from 1 to 2 to 3 ...
How can i fix this problem?
The problem is that changes to the UI should run on the event dispatch thread, but blocking this loop (and blocking the UI) will stop the screen from repainting. Instead, use a timer to perform regular updates, e.g.
Timer timer = new Timer();
ActionListener updater = new ActionListener()
{
int count;
public void actionPerformed(ActionEvent event) {
jLabel11.setText( Integer.toString(count++) );
if (count==60)
timer.stop();
}
}
timer.setDelay(100);
timer.addActionListener(updater);
timer.start();
See the Sun Tutorial - How to use Swing Timers.