JavaFX Canvas更新

时间:2014-08-14 03:08:28

标签: 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();
    }
}

1 个答案:

答案 0 :(得分:5)

  

我在绘制图像后尝试保存()图形文本,并在我想删除文本时调用restore(),但无效。

saverestore与删除文本等内容无关,他们所做的就是在堆栈中保存各种设置的状态,例如描边或填充以用于绘制形状并允许它们从堆栈弹出以便以后申请。这些例程根本不会影响画布上绘制的像素。

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

  

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

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

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


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