JavaFX快照异常:资源已经过时了很多次

时间:2014-04-30 02:13:18

标签: canvas javafx render snapshot illegalstateexception

我正在创建一个游戏,我在其中创建自定义赛道并将其作为字符串存储在数据库中。我这样做是通过绘制Canvas,使用快照创建WritableImage,然后使用PixelReader逐个读取像素,为每种颜色存储不同的字符(在游戏中,它是一个不同的对象,例如起点,终点线,墙等)。

我创造的每一条赛道上的一切都运转良好,但另一方面我按下按钮以保存赛道(即使我退出了以前的舞台,我正处于一个新阶段),我得到这个例外:

java.lang.IllegalStateException: Resource obsoleted too many times at com.sun.prism.impl.ManagedResource.contentsNotUseful(ManagedResource.java:461) at com.sun.prism.impl.BaseTexture.contentsNotUseful(BaseTexture.java:278) at com.sun.javafx.sg.prism.NGCanvas.renderStream(NGCanvas.java:819) at com.sun.javafx.sg.prism.NGCanvas.renderContent(NGCanvas.java:578) at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2043) at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1951) at com.sun.javafx.tk.quantum.QuantumToolkit$18.draw(QuantumToolkit.java:1318) at com.sun.javafx.tk.quantum.QuantumToolkit$18.run(QuantumToolkit.java:1354) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:129) at java.lang.Thread.run(Thread.java:745)

我认为这与快照未完全渲染有关,但我不知道如何解决问题。

我尝试启动一个新线程并使用“Thread.sleep(1000)”只是为了给它一些时间来完成渲染,就像我在https://community.oracle.com/thread/2579185中看到的那样 但它没有改变任何东西。

编辑:这是一个SSCCE

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class ExceptionClass extends Application {

    Canvas c;
    GraphicsContext gc;
    WritableImage temp;
    int x = 0, y = 0;

    @Override
    public void start(Stage primaryStage) {
        c = new Canvas(400, 400);
        gc = c.getGraphicsContext2D();
        gc.setStroke(Color.BLACK);
        gc.setLineWidth(5.0);
        temp = c.snapshot(null, temp);
        Button btn = new Button("Damn you, stupid exception!");
        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("Altering the canvas...");
                gc.strokeOval(x, y, 20, 20);
                PixelWriter pr = gc.getPixelWriter();
                pr.setColor(x + 10, y + 10, Color.RED);
                temp = c.snapshot(null, temp);
                x += 20;
                y += 20;
            }
        });
        StackPane root = new StackPane();
        root.getChildren().addAll(c, btn);

        Scene scene = new Scene(root, 800, 800);

        primaryStage.setTitle("Exception!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

}

我的假设是错误的。事实证明,我创建的PixelWriter导致了这个异常。之前我没有提到它,因为我认为这是无关紧要的,它的工作就是改变1个像素的颜色来指示我的游戏的起点,这就是为什么只有在我保存曲目时才需要调用它。 我仍然想知道为什么抛出这个异常:)

1 个答案:

答案 0 :(得分:1)

报告为RT-33294。根据错误报告,它在8.0.0中是一个回归,所以它应该在之前的版本以及8.0.0_20及更高版本中正常工作。

8.0.0和8.0.0_05建议的解决方法是拨打setPixels而不是setColor

                PixelWriter pr = gc.getPixelWriter();
//                pr.setColor(x + 10, y + 10, Color.RED);
                pr.setPixels(x + 10, y + 10, 1, 1, PixelFormat.getIntArgbInstance(), new int[] { 0xffff0000 }, 0, 1);
                temp = c.snapshot(null, temp);