Issue
I have a JavaFX application that gets CPU and Memory problems after the computer is going to sleep or hibernate.
In the application, I use a Canvas that is painted two times a second. This may cause issues. I am wondering if it's possible to detect when the computer is sleeping, and not repaint it. Maybe the canvas.isVisible() is already checking this?
Solution
You could only paint if your app has focus.
This can be achieved by pausing the animation when your application's main window no longer has focus.
You can monitor the stage's focusedProperty()
to find out when the stage has focus.
I ran some tests on a Mac (OS X 12.3) with JavaFX 18 and found that when the computer is put to sleep (click the apple icon in the menu bar and select Sleep), the focus is removed from the application, which allows the animation for the application to be paused while it does not have focus.
Example application
import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class SleepyApp extends Application {
private long start;
private Counter continuousCounter = new Counter();
private Counter focusedCounter = new Counter();
@Override
public void start(Stage stage) throws Exception {
VBox layout = new VBox(10,
focusedCounter.getCounterLabel(),
continuousCounter.getCounterLabel()
);
layout.setPrefSize(80, 80);
layout.setAlignment(Pos.CENTER);
stage.setScene(new Scene(layout));
stage.show();
stage.focusedProperty().addListener((observable, wasFocused, isFocused) -> {
if (isFocused) {
focusedCounter.play();
} else {
focusedCounter.pause();
}
});
continuousCounter.play();
focusedCounter.play();
start = System.currentTimeMillis();
}
@Override
public void stop() throws Exception {
long stop = System.currentTimeMillis();
continuousCounter.stop();
focusedCounter.stop();
long elapsed = (stop - start) / 1_000;
System.out.println("Elapsed: " + elapsed + " seconds.");
System.out.println("Continuous Counter: " + continuousCounter.getCount() + " seconds.");
System.out.println("Focused Counter: " + focusedCounter.getCount() + " seconds.");
}
public static void main(String[] args) {
launch(args);
}
class Counter {
private final Timeline timeline;
private final IntegerProperty count;
private final Label counterLabel;
public Counter() {
count = new SimpleIntegerProperty(0);
counterLabel = new Label(count.asString().get());
counterLabel.textProperty().bind(
count.asString()
);
counterLabel.setStyle("-fx-font-size: 20px");
timeline = new Timeline(
new KeyFrame(
Duration.seconds(1),
e -> count.set(count.get() + 1)
)
);
timeline.setCycleCount(Timeline.INDEFINITE);
}
public int getCount() {
return count.get();
}
public Label getCounterLabel() {
return counterLabel;
}
public void play() {
timeline.play();
}
public void pause() {
timeline.pause();
}
public void stop() {
timeline.stop();
}
}
}
Output
In this case, the computer was put to sleep for 16 seconds.
The first number is the number of one per second animation frames rendered only when the application has focus.
The second number is the number of one per second animation frames rendered regardless of whether the application has focus (and sleep state).
Elapsed: 30 seconds.
Continuous Counter: 30 seconds.
Focused Counter: 14 seconds.
On isVisible()
node.isVisible()
is not applicable for this case.
This is a description of the isVisible method:
Specifies whether this Node and any subnodes should be rendered as part of the scene graph. A node may be visible and yet not be shown in the rendered scene if, for instance, it is off the screen or obscured by another Node. Invisible nodes never receive mouse events or keyboard focus and never maintain keyboard focus when they become invisible.
As the documentation indicates, the node may be visible but not shown in the rendered scene, which will be the case when the computer is sleeping.
Answered By - jewelsea
Answer Checked By - Pedro (JavaFixing Volunteer)