So I'm a bit stuck on this one. I have a pretty basic game where you move a ship around a grid with arrow keys.
I added another thread with some monster that are supposed to automatically roam the grid. I can see from print statements that the thread is running an the Monster is moving, however, the image location is not being updated.
I found some similar questions and there's many recommendations to use Platfrom.runLater
. But I'm unsure if it fits my specific case, and if it does, how to implement it.
Here is what the Monster class is doing, moving the monster right one space every second. Like I mentioned, I'm logging the current location every time setX()
is called, so I can see that the location is being updated.
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);
}
}
}
And here is the JavaFX thread.
/* 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();
}
I can provide more code if needed, this is all I thought was relevant at the moment.
So again, my question, how can I update the UI of a JavaFX thread from another thread?