JavaFX Canvas更新

nru*_*n29 2 javafx-8

我一直在努力将我的应用程序从Swing切换到JavaFX.我一直在做一个房间逃脱游戏,它显示用户点击的项目的描述.在Swing中,我将子类化JComponent并覆盖该paintComponent(Graphics)方法.我可以在那里绘制文本,知道不断调用该方法来更新屏幕.但是,使用JavaFX Canvas时,没有不断调用的方法,这使得此任务更难.我尝试save()GraphicsContext之后我画了图像并restore()在我想要删除文本时调用,但无济于事.这是重要的代码:

package me.nrubin29.jescape;

import javafx.application.Platform;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.shape.Rectangle;

import java.util.Timer;
import java.util.TimerTask;

public class RoomPane extends Canvas {

    private Room room;

    private Toast toast;

    public RoomPane() {
        super(640, 480);

        setOnMouseClicked(e -> {
            for (JObject o : room.getObjects()) {
                if (o.getBounds().contains(e.getX(), e.getY())) {
                    toast = new Toast(o.getDescription());
                }
            }
        });

        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                if (toast == null) {
                    return;
                }

                if (toast.decrement()) { // Decrements the internal counter. If the count is 0, this method returns true.
                    toast = null;
                    Platform.runLater(() -> getGraphicsContext2D().restore());
                }

                else {
                    Platform.runLater(() -> getGraphicsContext2D().strokeText(toast.getText(), 300, 100));
                }
            }
        }, 0, 1000);
    }

    public void changeRoom(Room room) {
        this.room = room;

        GraphicsContext g = getGraphicsContext2D();

        g.drawImage(room.getBackground(), 0, 0);

        for (JObject o : room.getObjects()) {
            g.drawImage(o.getImage(), getCenterX(o.getBounds()), getCenterY(o.getBounds()));
        }

        g.save();
    }
}
Run Code Online (Sandbox Code Playgroud)

jew*_*sea 6

我在绘制图像后尝试save()ing Graphics(),当我想删除文本时调用restore(),但无济于事.

保存恢复与删除文本之类的东西无关,他们所做的就是在堆栈中保存各种设置的状态,例如描边或填充以用于绘制形状并允许它们从堆栈中弹出以便稍后应用.这些例程根本不影响画布上绘制的像素.

要从GraphicsContext中删除某些内容,您可以绘制它或清除它.对于您的代码,您可以执行的操作是在您尝试保存它的画布节点上快照,然后将快照图像绘制到您尝试还原它的画布上.它可能不是处理绘图的最有效方式(一个更聪明的例程,它只绘制文本更好的受损区域,但可能不需要你的简单游戏).

但是,使用JavaFX Canvas,没有不断调用的方法

使用AnimationTimer时间轴,而不是使用计时器来触发画布调用.AnimationTimer有一个回调方法,每个脉冲调用一次(每秒60次,或者与JavaFX一样快,可以渲染帧,以较小者为准),因此它为您提供了基于JavaFX脉冲的渲染系统的有效钩子.时间轴可以具有在用户指定的持续时间调用的关键帧,并且每个关键帧可以具有在该持续时间调用的事件处理程序回调.

使用内置的JavaFX动画框架,您不必担心多线程问题,也不必担心像Platform.runLater这样的问题,这会使代码过于复杂,并且很容易导致细微而严重的错误.


在一种不相关的注释中,对于像这样的简单游戏,IMO你可能最好完全重新编码以使用JavaFX场景图而不是画布.这样你就可以在更高的抽象层次上工作,而不是剪裁区域并重新绘制受损的油漆组件.