- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我对这个有点卡住了。我有一个非常基本的游戏,你可以用箭头键在网格中移动一艘船。
我添加了另一个线程,其中包含一些应该自动在网格中漫游的怪物。我可以从打印语句中看到线程正在运行并且怪物正在移动,但是图像位置没有更新。
我发现了一些类似的问题,并且有很多使用 Platfrom.runLater
的建议。但我不确定它是否适合我的具体情况,如果适合,如何实现。
这就是 Monster 类正在做的事情,每秒将怪物向右移动一格。正如我提到的,每次调用 setX()
时我都会记录当前位置,因此我可以看到位置正在更新。
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import java.awt.Point;
public class Monster implements Runnable {
private Point currentPoint;
private OceanMap map;
public Monster(int x, int y) {
this.currentPoint = new Point(x, y);
this.map = OceanMap.getInstance();
}
public Point getLocation() {
System.out.println(this.currentPoint.toString());
return this.currentPoint;
}
private void setNewLocation(Point newLocation) {
this.currentPoint = newLocation;
}
private void setY(int newY) {
this.currentPoint.y = newY;
this.setNewLocation(new Point(this.currentPoint.x, this.currentPoint.y));
}
private void setX(int newX) {
this.currentPoint.x = newX;
this.setNewLocation(new Point(this.currentPoint.x, this.currentPoint.y));
System.out.println(this.currentPoint.toString());
}
// public void addToPane() {
// System.out.println("this is called");
// iv.setX(this.currentPoint.x + 1 * 50);
// iv.setY(this.currentPoint.y * 50);
// obsrvList.add(iv);
// }
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setX(this.currentPoint.x + 1);
}
}
}
这是 JavaFX 线程。
/* Monster resources */
private Image monsterImage = new Image(getClass().getResource("monster.png").toExternalForm(), 50, 50, true, true);
private ImageView monsterImageView1 = new ImageView(monsterImage);
private Monster monster1;
private Thread monsterThread;
@Override
public void start(Stage oceanStage) throws Exception {
root = new AnchorPane();
scene = new Scene(root, scale * xDimensions, scale * yDimensions);
oceanStage.setScene(scene);
oceanStage.setTitle("Ocean Explorer");
/* Draw Grid */
for (int x = 0; x < xDimensions; x++) {
for (int y = 0; y < yDimensions; y++) {
Rectangle rect = new Rectangle(x * scale, y * scale, scale, scale);
rect.setStroke(Color.BLACK);
rect.setFill(Color.PALETURQUOISE);
root.getChildren().add(rect);
}
}
oceanStage.show();
monsterThread = new Thread(monster1);
monsterThread.start();
Platform.runLater(() -> {
monsterImageView1.setX(monster1.getLocation().x * scale);
monsterImageView1.setY(monster1.getLocation().y * scale);
root.getChildren().add(monsterImageView1);
});
startSailing();
}
如果需要,我可以提供更多代码,这就是我目前认为相关的所有代码。
我的问题又来了,如何从另一个线程更新 JavaFX 线程的 UI?
最佳答案
当您更新 Monster
内的 currentPoint
时,该值永远不会传播到 monsterImageView1
。您应该将 currentPoint
转换为属性,然后绑定(bind)到它:
class Point {
final int x;
final int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
class Monster implements Runnable {
private ReadOnlyObjectWrapper<Point> location = new ReadOnlyObjectWrapper<>();
public Monster(int x, int y) {
setLocation(new Point(x, y));
}
public Point getLocation() {
return this.location.get();
}
private void setLocation(Point location) {
this.location.set(location);
}
public ReadOnlyProperty<Point> locationProperty() {
return this.location.getReadOnlyProperty();
}
private void setY(int newY) {
this.setLocation(new Point(this.getLocation().x, newY));
}
private void setX(int newX) {
this.setLocation(new Point(newX, this.getLocation().y));
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// run the update on the FX Application Thread for thread safety as well as to prevent errors in certain cases
Platform.runLater(() -> this.setX(this.getLocation().x + 1));
}
}
}
monsterThread = new Thread(monster1);
monsterThread.start();
monsterImageView1.xProperty().bind(Bindings.createIntegerBinding(() -> monster1.getLocation().x * scale, monster1.locationProperty()));
monsterImageView1.yProperty().bind(Bindings.createIntegerBinding(() -> monster1.getLocation().y * scale, monster1.locationProperty()));
root.getChildren().add(monsterImageView1);
<小时/>
但是,正如 @James_D 提到的,Timeline
以正确的方式解决这个问题将是一个更好的方法:
class Monster {
private ReadOnlyObjectWrapper<Point> location = new ReadOnlyObjectWrapper<>();
private Timeline timeline;
public Monster(int x, int y) {
setLocation(new Point(x, y));
timeline = new Timeline(new KeyFrame(Duration.seconds(1), event -> {
setX(getLocation().x + 1);
}));
timeline.setCycleCount(Timeline.INDEFINITE);
}
public void start() {
timeline.play();
}
// NOTE: remember to call stop() or this will result in a memory leak
public void stop() {
timeline.stop();
}
public Point getLocation() {
return this.location.get();
}
private void setLocation(Point location) {
this.location.set(location);
}
public ReadOnlyProperty<Point> locationProperty() {
return this.location.getReadOnlyProperty();
}
private void setY(int newY) {
this.setLocation(new Point(this.getLocation().x, newY));
}
private void setX(int newX) {
this.setLocation(new Point(newX, this.getLocation().y));
}
}
关于JavaFX 从另一个线程更新 AnchorPane,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50671047/
我正在编写一个 JavaFX 应用程序,顶部有一个菜单栏,下面有一个 AnchorPane,我可以在其中使用其他 FXML 文件来显示内容。问题是当代码运行时,即使我将 Vgrow 设置为“始终”,其
正如标题所示,我创建了一个根 AnchorPane,其中放置了两个 AnchorPane,上部 AnchorPane 以某种方式变得圆滑,但在下部 AnchorPane 的情况下,上侧是圆角的,而下侧
所以我正在致力于构建一个类似于 IDE 的应用程序,例如 Eclipse 或 Netbeans。我想要有不同的区域,用户可以选择一些内容,例如将显示在其中一个区域中的 View 。我的第一次尝试是将控
我想创建一个基于GridPane的应用程序。为了实现自适应性,我使用 AnchorPane。布局在宽度上延伸得很好,但在高度上却很糟糕。如何修复?
我有一个 TabPane,其中包含两个 Tab,并在 FXML 中设置。初始化时,我动态地将 AnchorPane 添加到 Tab 之一。然后,我将 ListView 设置为 AnchorPane 的
所以我对这个有点卡住了。我有一个非常基本的游戏,你可以用箭头键在网格中移动一艘船。 我添加了另一个线程,其中包含一些应该自动在网格中漫游的怪物。我可以从打印语句中看到线程正在运行并且怪物正在移动,但是
我初始化了一些不是我的锚定 Pane 的元素: AnchorPane root = new AnchorPane(listLoader.load(), textareaLoader.load(), f
对于一个项目,我得到了代码并且必须将其重构为 FXML,我正在尝试使用我得到的一段代码,它是 AnchorPane 的扩展,但是当我在 FXML 中将其从 AnchorPane 切换到 World 时
我正在尝试使鼠标事件在我的 javaFx 中工作。我希望能够向我的 anchor 面板添加鼠标事件,但我似乎无法使其工作。 room = new AnchorPane(); r
您好,我有以下代码,我在 anchor Pane 内添加一个圆圈,并在圆圈上添加文本。 Circle是一个Circle,ArrayList,有多个圆圈。 pane.getChildren().
我有一列有 3 行。每行包含一个图像。此列是 GridPane 的子项。如您在以下 FXML 中所见:
我在 AnchorPane 内有一个 JavaFX Label,它包含在 VBox 中。这个位于 ScrollPane 中。我希望文本自动换行并自动适应窗口的宽度。 这是我的代码的简化示例: publ
这似乎是一个简单的问题,但我还没有找到相关的答案。 我正在创建一个简单的 Javafx 应用程序,并在单击时创建可以拖动的节点。 我想确保特定类型的节点(圆形)始终绘制在 AnchorPane 顶部。
我正在做一个项目,我需要你的帮助。 我想知道是否可以将 percentage 中的锚定 Pane 约束设置为类似 AnchorPane.setLeftAnchor(content1, 35%); 最佳
我正在使用 SceneBuilder 8.0.0 和 JavaFX 8。 我有一个 Button btn 和一个 Label lbl 附加到 AnchorPane ap。 当应用程序启动时,btn 和
我有 AnchorPane根 根目录下的HBox HBox中有两个VBox,每个都没有名字,new AnchorPane和带有文本的每个 AnchorPane 中的无名标签 有表格,只是模板不适合我。
我正在使用 sceneBuilder。 How to clear an AnchorPane ? Is there a way to delete all the nodes contained in
我希望我的 Javafx 组件(如标签、TextFields 分别包装在 VBox 中)保持在窗口的中央,即使它已调整大小。见附件图片。目前这些组件包含在 anchorPane 中。FXML 文件代码
我正在 javafx 中创建一个小应用程序。我想设置背景颜色,所以以下是我的 FXML 代码..我需要如何设置背景颜色
我会将我的锚定 Pane 打印为 png:我在我的 Controller 中加载了一个图像并写了一些文本,而不是我想保存整个面板,但我不知道我必须使用哪些工具。 URL fxmlpath = this
我是一名优秀的程序员,十分优秀!