JavaFX pausing during for loop WITHOUT using Thread.Sleep() - java

I'm coding this in JavaFX using a FXMLController and the scene builder.
I'm currently creating an Instagram "liker" mostly just for practice as I'm a Computer Science major, and I just like coding.
My issue is, I have a for loop that "likes" 20 photos for each hashtag, I obviously need a delay or I'd get banned rather quickly. The user can choose the delay, then I randomize this delay so it's not too robotic.
The only way I've been able to use this delay is through the thread.sleep method, but since I'm coding on the FXMLController, it freezes the whole UI, and somehow stops other textareas from being updated. This is obviously not ideal.
I've looked everywhere trying to find an alternative to this, but I can't find anything that works in my program.
I'll give the whole method:
private void start() {
sleepWhen();
tagNumber++;
int delays = Integer.valueOf(delay.getText());
delays = delays * 1000;
if (loaded) {
runTime.clear();
runTime.appendText("Liking...");
for (int i = 0; i < 20; i++) {
webEngine.executeScript("document.getElementsByClassName('btn btn-default btn-xs likeButton')[" + i + "].click()");
try {
double random = Math.random() * 1000;
random = random + delays;
delays = (int) random;
System.out.println(delays);
likes++;
likesNumber.clear();
likesNumber.appendText(String.valueOf(likes));
System.out.println(String.valueOf(likes));
Thread.sleep(delays);
delays = Integer.valueOf(delay.getText());
delays = delays * 1000;
} catch (InterruptedException ex) {
//do nothing
}
System.out.println("tag number" + tagNumber + "numbertags" + numberTags);
if (!sleep) {
if (tagNumber < numberTags) {
System.out.println("Loading tag:" + tagNumber);
loadTag(tagNumber);
}
}
}
}
}
This likes 20 photos, then loads another hashtag, and repeats.
Any help with this would be great, thanks.

The freeze is because you are trying to do everything on the same thread, when you are using Thread.sleep(delays), you are actually putting your UI thread to sleep and hence the lag !
Try using different thread for your work, you can either use a worker thread, if whatever you are doing will not affect the UI
or you can use Platform.runLater(), if you want the changes to shown on the UI !
For more details :
concurrency in javafx !
Platform.runLater and Task in JavaFX

Related

Java drawing with delay

I'm trying to visualize various graph-algorithms. I want to make it so, that after every 2 seconds the graph get updated and gets repainted. I have tried using the Thread.sleep() method but it just freezes the GUI and then after a while is done with the complete algorithm.
(I am fairly new to Java so don't be to harsh with the code)
The Code in question:
else if(ae.getSource() == fordFulkersonButton){
dinicButton.setEnabled(false);
edmondsKarpButton.setEnabled(false);
gtButton.setEnabled(false);
if(checkbox.isEnabled()){
fordFulkersonButton.setEnabled(false);
while(!fordFulkerson.getIsDone()){
flowNetwork = fordFulkerson.algoFF(flowNetwork);
popupText.setVisible(true);
Integer i = new Integer(flowNetwork.getCurrentFlow());
String s = i.toString();
popupText.setText("Aktueller Fluß: "+s);
graphDrawer.setFlowNetwork(flowNetwork);
this.showFrame();
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Integer in = new Integer(flowNetwork.getCurrentFlow());
String st = in.toString();
popupText.setText("Algorithmus is beendet mit Fluss: "+st);
}
flowNetwork = fordFulkerson.algoFF(flowNetwork);
popupText.setVisible(true);
Integer i = new Integer(flowNetwork.getCurrentFlow());
String s = i.toString();
if(fordFulkerson.getIsDone()){
popupText.setText("Algorithmuss beednet mit maximalen Fluß: "+s);
}else{
popupText.setText("Aktueller Fluß: "+s);
}
graphDrawer.setFlowNetwork(flowNetwork);
this.showFrame();
}
Doing huge amounts of work in a UI thread freezes the UI. If you want to do animations or complex work, use a worker thread or a Swing timer.
You must not call Thread.sleep() in Swing UI code. Instead, you need to think like an animator: Show one frame of the animation at a time. Some external source will call your code to show the next frame. The external source is the Swing timer. Your code draws the next frame and returns. That way, you never block the UI thread for long.
Google for "swing animation". Interesting results are:
http://www.java2s.com/Tutorial/Java/0240__Swing/Timerbasedanimation.htm
http://zetcode.com/tutorials/javagamestutorial/animation/

Keeping timer events equally spaced

I'm attempting to get an animation working in a game I'm developing. The animation works by setting a button size to very small, then gradually growing it to its normal size again. I have it working, except I'm having timing issues.
Sometimes the button will grow almost instantly, sometimes it goes VERY slow. I'm looking for something inbetween, and I need it to ALWAYS grow at that size, not some times fast sometimes slow.
I've looked into it and I found this pseudocode:
distance_for_dt = speed * delta_time
new_position = old_position + distance_for_dt
Unfortunately I don't understand what's being said, and I don't know how to apply this to my code. Can anyone help with that or explain what's being said in the above pseudocode?
Here's my timer code, timer is already defined above as a Timer, and z[] is just a pair of coordinates:
timer = new Timer(18, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Dimension dim = button[z[0]][z[1]].getSize();
if (dim.getHeight() < 79.9) {
button[z[0]][z[1]].setSize((int) (dim.getWidth() + 6), (int) (dim.getHeight() + 6));
} else {
button[z[0]][z[1]].setSize(80, 80);
timer.stop();
}
}
});
timer.start();
Depending on how many updates you're calling on your Swing application, it may be getting "backed up" and slowing down. For instance, if you wanted to accomplish the animation without a Timer, you could just do something like this:
// example method to do animation
public void animateButton(final int wait){
Thread thread = new Thread(){
public void run(){
// some loop structure to define how long to run animation
Dimension dim = button[z[0]][z[1]].getSize();
while (dim.getHeight() < 79.9){
SwingUtilities.invokeLater(new Runnable(){
//update Swing components here
});
try{ Thread.Sleep(wait); }
catch(Exception e){}
}
}
}
}
thread.start();
}
I think this may be similar to how a Timer updates the GUI, as Timers run on a separate thread. I would look into whether or not you need to use invokeLater(new Runnable) inside a timer to properly schedule the task. I had to do this to allow a project I was working on to keep responsive during long tasks. If you really needed to ensure the speed and maybe DROP updates to adjust for system lag, then you'll need to be calculating how complete the animation is vs how much time has passed, using a method call such as System.currentTimeMillis() or System.nanoTime(). Then, adjust accordingly for each step of the animation.

How to loop an array of points with delay in java?

I'm trying to loop trough an array of Points with a delay, but nothing happens and I don't get errors.
Here's an example of what my code looks like:
public class Class {
private Point[] points;
private int start, delay;
public Class() {
points = new Point[] {
new Point(1, 1),
new Point(2, 1),
new Point(1, 2)
};
start = System.nanoTime();
delay = 500;
}
public void update() {
for(int i = 0; i < points.length; i++) {
long elapsed = (System.nanoTime() - startT) / 1000000;
if(elapsed > delay) {
System.out.println("x: " + points[i].x);
System.out.println("y: " + points[i].y);
start = System.nanoTime();
}
}
}
}
Everything inside the update function is working except for that for loop.
edit:
It's a java Swing application with only 1 thread.
One of your problems is that you're using an if block and not a while loop. An if block just checks once, sees that the condition is false, and skips over it. A while loop will loop until the condition is false.
For most delays you could use a general purpose Timer object such as a java.util.Timer together with a java.util.TimerTask object.
for delays in a Swing GUI you would use a javax.swing.Timer
Other options for general non-Swing computing including using a while loop that contains a Thread.sleep(...) call.
Also look into using a ScheduledThreadPoolExecutor for non-Swing delays.
Edit
Regarding your edit:
edit: It's a java Swing application with only 1 thread.
Then use a javax.swing.Timer. You can find the tutorial here: Swing Timer Tutorial
And here's the Swing Concurrency Tutorial
Also have a look at the Swing Tutorial for more on Swing development.
If you need more help, then as we've already mentioned, provide more detail in your question.
To sleep for an aproximate amount of time use Thread.sleep(millis);
Do not expect accuracy to be more than 30ms.

Java Swing GUI freezes - observer pattern

For a program I am creating I have used the observer pattern, yet whilst my Observable sends data almost constantly, simulated with a loop here because the actual code is hooked up to a device and measures the data, my update(); method runs as it should but swing doesn't.
Swing only updates the JTextField AFTER the loop has finished, yet when I use System.out.println() it iterates nicely each update.
Observable code:
public void collectData()
{
for(int i = 0; i < 10; i++)
{
currRandom = (Math.random() * 10);
for(Observer o : observers)
{
notify(o);
}
}
}
Observer (SWING) code:
public void update()
{
jRecievedData.setText(jRecievedData.getText() + "\n" + Double.toString(PVC.pc.getCurr()));
jlAverage.setText("Average: " + PVC.getAverage());
jlMin.setText("Minimum: " + PVC.getMin());
jlMax.setText("Maximum: "+ PVC.getMax());
// setText updates slow
}
Any help would be greatly appreciated! (I have the feeling this is going to be a threading problem , but I'm not sure and if it is, I still don't know how to do that with swing)
Instead of looping through your observers explicitly, let Observable do it, as shown here.
this.setChanged();
this.notifyObservers();
Also, verify that you are not blocking the event dispatch thread. If so, consider using SwingWorker, which greatly simplifies Swing threading.

How to use a sleep/wait function to display a countdown

I want my program to start off using a countdown timer that will be displayed to the user. The only way I can think to do that is to label.setText() and Thread.sleep(). I've tried for about 20min trying to get it to work, but can't seem to crack it. Help?
Use a Swing timer. Basically you create a class that implements ActionListener, create a javax.swing.Timer, and the actionPerformed method of the ActionListener gets called at an interval you specify. In your actionPerformed method, check the time, and update the value to be displayed when appropropriate, and call repaint(). Use an interval of 0.1 second, and your countdown will be smooth and accurate enough.
I wouldn't count on the accuracy of Thread.sleep, but:
for(int i = 20; i >= 0; i--) {
label.setText(i + " seconds remaining");
Thread.sleep(1000);
}
This will, of course, block the UI thread while sleeping, so you probably need to run it on a separate thread. This means you will need something like SwingUtilities.InvokeLater to update the UI, since you are using a thread different than the UI one:
for(int i = 20; i >= 0; i--) {
SwingUtilities.InvokeLater(new Runnable() {
public void run() {
label.setText(i + " seconds remaining");
}
});
Thread.sleep(1000);
}

Categories

Resources