JavaFX8演示视图(重复的窗格和内容)

JavaFX8演示视图(重复的窗格和内容),javafx,snapshot,Javafx,Snapshot,我正在尝试为我的绘图应用程序创建演示视图,其中只有绘图板(窗格)可见。因此,用户可以在投影仪上显示演示视图,同时在PC上显示实际的绘图窗格和工具 我目前的方法是从每个帧中的窗格创建一个快照,并在第二阶段的ImageView中显示它 public void startStream(){ new AnimationTimer() { @Override public void handle(long now) { WritableIm

我正在尝试为我的绘图应用程序创建演示视图,其中只有绘图板(窗格)可见。因此,用户可以在投影仪上显示演示视图,同时在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%。我可以理解,在每一帧上创建一个图像是没有效率的,这就是为什么我想问,是否有一种方法可以让它更有效地工作


此外,如果有更好的方法/解决方案来实现此功能,我将不胜感激。

为了减少CPU使用,不要在动画计时器中创建快照这确实会以帧速率(60 FPS)频率创建快照,即使
绘图窗格中没有任何更改。相反,在
绘图窗格的布局之后创建快照。将侦听器添加到
drawingPane
needsLayoutProperty
应该可以实现以下功能:

drawingPane.needsLayoutProperty().addListener((obs, wasDirty, isDirty) -> {
    if(!isDirty) {
        WritableImage image = drawingPane.snapshot(new SnapshotParameters(), null);
        stream.setImage(image);
    }
});
当您不编辑
绘图窗格时,这将降低CPU使用率

它还可以降低内存使用率,因为垃圾收集器可以更快地启动并收集旧快照。如果没有,请考虑重新使用<代码> WrrababIVIEWION/COMPUTE实例,如果它已经具有正确的大小:

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
的子级是托管子级(这是默认设置),因此它们的布局被标记为脏会导致
drawingPane
的布局被标记为脏,这样您就可以实际观察到
needsLayout
属性的任何更改。

谢谢,这将CPU使用率降至10%以下,内存使用率降至350MB以下