javafx-8 - JavaFX Canvas 更新

标签 javafx-8

我一直致力于将我的应用程序从 Swing 切换到 JavaFX。我一直在开发一款密室逃脱游戏,它会显示用户点击的项目的描述。在 Swing 中,我将 JComponent 子类化并覆盖 paintComponent(Graphics) 方法。我可以在那里绘制文本,因为我知道不断调用该方法来更新屏幕。但是,使用 JavaFX Canvas 时,没有不断调用的方法,这使得这项任务变得更加困难。我在绘制图像后尝试 save()ing 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();
    }
}

最佳答案

I attempted save()ing the GraphicsContext after I drew the images and called restore() when I wanted to remove the text, but to no avail.

saverestore与删除文本等内容无关,它们所做的是将各种设置的状态(如笔触或填充)保存在堆栈中以用于绘制形状,并允许它们从堆栈中弹出以供以后应用。这些例程根本不会影响在 Canvas 上绘制的像素。

要从 GraphicsContext 中删除某些内容,您可以在其上绘制,或者 clear它。对于您的代码,您可以做的是 snapshot您尝试保存它的 Canvas 节点,然后将您的快照图像绘制到您尝试恢复它的 Canvas 上。它可能不是处理绘图的最有效方法(更智能的例程只绘制文本所在的损坏区域会更好,但对于您的简单游戏可能不需要)。

However, using the JavaFX Canvas, there is no method that is called constantly

与其使用计时器来触发 Canvas 调用,不如使用 AnimationTimerTimeline . AnimationTimer 有一个回调方法,它在每个脉冲(每秒 60 次,或 JavaFX 可以渲染帧的速度,以较小者为准)中调用,因此它为您提供了一个有效的钩子(Hook)到基于 JavaFX 脉冲的渲染系统。时间轴可以有在用户指定的持续时间调用的关键帧,每个关键帧可以有一个在该持续时间调用的事件处理程序回调。

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


在一种不相关的说明中,对于像这样的简单游戏,IMO 你最好完全重新编码它以使用 JavaFX 场景图而不是 Canvas 。这样,您将在更高的抽象级别上工作,而不是裁剪区域和重新绘制损坏的绘制组件。

关于javafx-8 - JavaFX Canvas 更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25299404/

相关文章:

javafx-2 - 堆叠条形图的限制宽度大小

javafx-8 - VBox 中的按钮重叠

performance - JavaFX 吃掉我的内存?

javafx-2 - java.lang.IllegalArgumentException : Invalid URL or resource not found

java - 在 JavaFX 中为面板中的对象设置相机

JavaFX ChoiceBox 添加具有类型安全性的分隔符

Javafx: 链接 fx:id-s

javafx - 如何获取鼠标在图表空间中的位置

java - Tooltip:如何获取触发提示的鼠标坐标?

java - 显示后台任务的进度