JavaFX8 演示视图(重复窗格和内容)
JavaFX8 presentation view (duplicate pane and content)
我正在尝试为我的绘图应用程序创建演示视图,其中只有绘图板(窗格)可见。因此,用户可以在投影仪上显示演示视图,同时在 PC 上拥有实际的绘图窗格和工具。
我目前的做法是从每一帧的窗格中创建一个快照,并在第二阶段的 ImageView 中显示它。
public void startStream(){
new AnimationTimer() {
@Override
public void handle(long now) {
WritableImage image = drawingPane.snapshot(new SnapshotParameters(), null);
stream.setImage(image);
}
}.start();
final Screen screen = Screen.getPrimary();
final Stage stage = new Stage();
StackPane root = new StackPane();
root.getChildren().add(stream);
Scene scene = new Scene(root, drawingPane.getWidth(), drawingPane.getHeight());
stage.setScene(scene);
stage.setTitle("streaming stage");
Rectangle2D bounds = screen.getBounds();
System.out.println(bounds);
stage.setX(bounds.getMinX() + (bounds.getWidth() - 300) / 2);
stage.setY(bounds.getMinY() + (bounds.getHeight() - 200) / 2);
stage.show();
}
这里的问题是它占用了大量 RAM,比如 800MB,而且 CPU 使用率增加了 30%。我可以理解,在每一帧上创建图像效率不高,这就是为什么我想问一下,是否有办法使它更有效地工作。
此外,如果有更好的 approach/solution 此功能,我将不胜感激。
为了减少 CPU 的使用,不要在 AnimationTimer 中制作快照——这实际上是以帧速率 (60 FPS) 频率制作快照,即使 drawingPane
.相反,在 drawingPane
的布局之后制作快照。将侦听器添加到 drawingPane
的 needsLayoutProperty
应该可以解决问题:
drawingPane.needsLayoutProperty().addListener((obs, wasDirty, isDirty) -> {
if(!isDirty) {
WritableImage image = drawingPane.snapshot(new SnapshotParameters(), null);
stream.setImage(image);
}
});
当您不编辑 drawingPane
时,这应该会降低 CPU 的使用率。
它也可能会降低内存使用率,因为垃圾收集器可能会更快启动并收集旧快照。如果不是,请考虑 re-using WritableImage
实例,如果它已经具有正确的大小:
WritableImage image = null;
drawingPane.needsLayoutProperty().addListener((obs, wasDirty, isDirty) -> {
if(!isDirty) {
if(this.image != null &&
(this.image.getWidth() != drawingPane.getWidth() ||
this.image.getHeight() != drawingPane.getHeight())) {
this.image = null;
}
this.image = drawingPane.snapshot(new SnapshotParameters(), this.image);
stream.setImage(this.image);
}
});
注意,此答案假设 drawingPane
的 children 是 managed children(这是默认设置),因此它们的布局被标记为 dirty 导致 drawingPane
的布局被标记为脏的,因此您可以实际观察 needsLayout
属性.
我正在尝试为我的绘图应用程序创建演示视图,其中只有绘图板(窗格)可见。因此,用户可以在投影仪上显示演示视图,同时在 PC 上拥有实际的绘图窗格和工具。
我目前的做法是从每一帧的窗格中创建一个快照,并在第二阶段的 ImageView 中显示它。
public void startStream(){
new AnimationTimer() {
@Override
public void handle(long now) {
WritableImage image = drawingPane.snapshot(new SnapshotParameters(), null);
stream.setImage(image);
}
}.start();
final Screen screen = Screen.getPrimary();
final Stage stage = new Stage();
StackPane root = new StackPane();
root.getChildren().add(stream);
Scene scene = new Scene(root, drawingPane.getWidth(), drawingPane.getHeight());
stage.setScene(scene);
stage.setTitle("streaming stage");
Rectangle2D bounds = screen.getBounds();
System.out.println(bounds);
stage.setX(bounds.getMinX() + (bounds.getWidth() - 300) / 2);
stage.setY(bounds.getMinY() + (bounds.getHeight() - 200) / 2);
stage.show();
}
这里的问题是它占用了大量 RAM,比如 800MB,而且 CPU 使用率增加了 30%。我可以理解,在每一帧上创建图像效率不高,这就是为什么我想问一下,是否有办法使它更有效地工作。
此外,如果有更好的 approach/solution 此功能,我将不胜感激。
为了减少 CPU 的使用,不要在 AnimationTimer 中制作快照——这实际上是以帧速率 (60 FPS) 频率制作快照,即使 drawingPane
.相反,在 drawingPane
的布局之后制作快照。将侦听器添加到 drawingPane
的 needsLayoutProperty
应该可以解决问题:
drawingPane.needsLayoutProperty().addListener((obs, wasDirty, isDirty) -> {
if(!isDirty) {
WritableImage image = drawingPane.snapshot(new SnapshotParameters(), null);
stream.setImage(image);
}
});
当您不编辑 drawingPane
时,这应该会降低 CPU 的使用率。
它也可能会降低内存使用率,因为垃圾收集器可能会更快启动并收集旧快照。如果不是,请考虑 re-using WritableImage
实例,如果它已经具有正确的大小:
WritableImage image = null;
drawingPane.needsLayoutProperty().addListener((obs, wasDirty, isDirty) -> {
if(!isDirty) {
if(this.image != null &&
(this.image.getWidth() != drawingPane.getWidth() ||
this.image.getHeight() != drawingPane.getHeight())) {
this.image = null;
}
this.image = drawingPane.snapshot(new SnapshotParameters(), this.image);
stream.setImage(this.image);
}
});
注意,此答案假设 drawingPane
的 children 是 managed children(这是默认设置),因此它们的布局被标记为 dirty 导致 drawingPane
的布局被标记为脏的,因此您可以实际观察 needsLayout
属性.