JavaFx 画布内存优化

问题描述 投票:0回答:1

我的应用程序使用画布绘制图表,放置在多个选项卡窗格中。在宽屏显示器上,创建超过 10 个选项卡后,出现如下异常。 我认为这是来自 Canvas 的高视频内存使用率。

我的问题是,是否有任何方法可以释放 Canvas 内存使用量。我会为选项卡窗格中未选择的选项卡中的画布触发此操作。 我试着做 canvas.setSize(0,0),但这似乎并不总是有效。如果这适用于 canvas.setDisable(true) 就好了。

在高分辨率监视器上重现的代码。将标签数量减少到 5,一切正常。


import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class CanvasIssue extends Application {
    private final StackPane root = new StackPane();
    private final Scene scene = new Scene(root, 300, 250);


    @Override
    public void start(Stage stage) {
        stage.setTitle("Sample Canvas");

        TabPane tabPane = new TabPane();
        for ( int i = 0; i < 30; i++) {
            tabPane.getTabs().add(new Tab("Tab " + tabPane.getTabs().size(), setupCanvasPane()));
        }

        root.getChildren().add(tabPane);
        stage.setScene(scene);
        stage.sizeToScene();
        setupCanvasPane();
        stage.show();
    }
    private Pane setupCanvasPane(){
        final BorderPane pane = new BorderPane();
        final Canvas canvas = new Canvas(){
            @Override
            public boolean isResizable() {
                return true;
            }

            @Override
            public double prefWidth(double height) {
                return getWidth();
            }

            @Override
            public double prefHeight(double width) {
                return getHeight();
            }
        };
        pane.setCenter( canvas );
        canvas.widthProperty().bind(pane.widthProperty());
        canvas.heightProperty().bind(pane.heightProperty());
        pane.widthProperty().addListener((o,p,c)-> paint(canvas));
        paint( canvas );
        return pane;
    }

    public void paint( Canvas canvas ){
        GraphicsContext gr = canvas.getGraphicsContext2D();
        gr.clearRect( 0,0, canvas.getWidth(), canvas.getHeight() );
        gr.setFill( Color.web("#ffffff") );
        gr.fillRect( 0,0,canvas.getWidth(), canvas.getHeight());
        gr.setFont( Font.font( "Monospaced"));
        gr.setFill( Color.BLACK );
        gr.fillText("This is a", 50, 70 );
        gr.setFill( Color.RED );
        gr.fillText("demo", 50, 88 );
    }



    public static void main(String[] args) {
        launch(args);
    }
}


我通过更多选项卡获得的异常:

java.lang.NullPointerException: Cannot invoke "com.sun.prism.RTTexture.createGraphics()" because "<local9>" is null
    at com.sun.javafx.sg.prism.NGCanvas$RenderBuf.validate(NGCanvas.java:214)
    at com.sun.javafx.sg.prism.NGCanvas.initCanvas(NGCanvas.java:644)
    at com.sun.javafx.sg.prism.NGCanvas.renderContent(NGCanvas.java:607)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.renderForClip(NGNode.java:2313)
    at com.sun.javafx.sg.prism.NGNode.renderRectClip(NGNode.java:2207)
    at com.sun.javafx.sg.prism.NGNode.renderClip(NGNode.java:2233)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2066)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.renderForClip(NGNode.java:2313)
    at com.sun.javafx.sg.prism.NGNode.renderRectClip(NGNode.java:2207)
    at com.sun.javafx.sg.prism.NGNode.renderClip(NGNode.java:2233)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2066)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.renderForClip(NGNode.java:2313)
    at com.sun.javafx.sg.prism.NGNode.renderRectClip(NGNode.java:2207)
    at com.sun.javafx.sg.prism.NGNode.renderClip(NGNode.java:2233)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2066)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.renderForClip(NGNode.java:2313)
    at com.sun.javafx.sg.prism.NGNode.renderRectClip(NGNode.java:2207)
    at com.sun.javafx.sg.prism.NGNode.renderClip(NGNode.java:2233)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2066)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.renderForClip(NGNode.java:2313)
    at com.sun.javafx.sg.prism.NGNode.renderRectClip(NGNode.java:2207)
    at com.sun.javafx.sg.prism.NGNode.renderClip(NGNode.java:2233)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2066)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.renderForClip(NGNode.java:2313)
    at com.sun.javafx.sg.prism.NGNode.renderRectClip(NGNode.java:2207)
    at com.sun.javafx.sg.prism.NGNode.renderClip(NGNode.java:2233)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2066)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.renderForClip(NGNode.java:2313)
    at com.sun.javafx.sg.prism.NGNode.renderRectClip(NGNode.java:2207)
    at com.sun.javafx.sg.prism.NGNode.renderClip(NGNode.java:2233)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2066)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:480)
    at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:321)
    at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:92)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
    at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:126)
    at java.base/java.lang.Thread.run(Thread.java:832)

javafx canvas prism
1个回答
0
投票

我会尝试做的是虚拟化选项卡,以便仅当此选项卡成为选定选项卡时才分配画布,并在选择另一个选项卡时从场景图中删除画布。所以一次只存在一个可能的大画布。

© www.soinside.com 2019 - 2024. All rights reserved.