我一直致力于将我的应用程序从 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.
save和 restore与删除文本等内容无关,它们所做的是将各种设置的状态(如笔触或填充)保存在堆栈中以用于绘制形状,并允许它们从堆栈中弹出以供以后应用。这些例程根本不会影响在 Canvas 上绘制的像素。
要从 GraphicsContext 中删除某些内容,您可以在其上绘制,或者 clear它。对于您的代码,您可以做的是 snapshot您尝试保存它的 Canvas 节点,然后将您的快照图像绘制到您尝试恢复它的 Canvas 上。它可能不是处理绘图的最有效方法(更智能的例程只绘制文本所在的损坏区域会更好,但对于您的简单游戏可能不需要)。
However, using the JavaFX Canvas, there is no method that is called constantly
与其使用计时器来触发 Canvas 调用,不如使用 AnimationTimer或 Timeline . AnimationTimer 有一个回调方法,它在每个脉冲(每秒 60 次,或 JavaFX 可以渲染帧的速度,以较小者为准)中调用,因此它为您提供了一个有效的钩子(Hook)到基于 JavaFX 脉冲的渲染系统。时间轴可以有在用户指定的持续时间调用的关键帧,每个关键帧可以有一个在该持续时间调用的事件处理程序回调。
使用内置的JavaFX动画框架,你不用再担心多线程的问题,做类似Platform.runLater的事情这会使您的代码过于复杂,并且很容易导致细微而严重的错误。
在一种不相关的说明中,对于像这样的简单游戏,IMO 你最好完全重新编码它以使用 JavaFX 场景图而不是 Canvas 。这样,您将在更高的抽象级别上工作,而不是裁剪区域和重新绘制损坏的绘制组件。
关于javafx-8 - JavaFX Canvas 更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25299404/