如何强制Java FX场景刷新? [英] How to force Java FX scene refresh?

查看:269
本文介绍了如何强制Java FX场景刷新?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有开始按钮的Java FX场景和几个代表地图图块的矩形。我还绘制了一个代表我的探险家的球体(它必须探索地图),但是我在运行动画时遇到了困难。

I have an Java FX scene with a start button and several rectangles which represent the tiles of a map. I also have drawn a sphere which represents my explorer (it has to explore the map), but I am having difficulties with running the animation.

在我的OnMouseClicked处理程序中开始按钮,我开始一个探索地图的算法,该算法改变了球体的位置和已经访问过的瓷砖的颜色。问题是在算法运行时场景不会自动更新,因此我只能看到最终场景的样子(算法停止运行后)。如何强制进行场景更新,以便我可以按顺序查看所有颜色变化?

In my OnMouseClicked handler for the start button, I start an algorithm for exploring the map which changes the position of the sphere and the colors of the tiles which have been visited. The problem is that the scene won't update itself while the algorithm is running, so I only get to see how the final scene will look like (after the algorithm has stopped running). How can I force a scene update so I can see all the color changes sequentially?

稍后编辑:

import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class Test extends Application {

private static final double boxOuterSize = 50;
private static final double boxInnerSize = 48;
private static final double boxCornerRadius = 20;

private Stage applicationStage;
private Scene applicationScene;

private static double   sceneWidth  = 1024;
private static double   sceneHeight = 800;
private static HBox     container = new HBox();
private static Group    root = new Group();
private Rectangle[] rectangles = new Rectangle[10];

@Override
public void start(Stage mainStage) throws Exception {

    applicationStage = mainStage;
    container.setSpacing(10);
    container.setPadding(new Insets(10, 10, 10, 10));

    try {
        applicationScene = new Scene(container, sceneWidth, sceneHeight);
        applicationScene.addEventHandler(EventType.ROOT,(EventHandler<? super Event>)this);
        applicationScene.setFill(Color.WHITE);

    } catch (Exception exception) {
        System.out.println ("exception : "+exception.getMessage());
    }

    applicationStage.setTitle("HurtLockerRobot - Tema 3 IA");
    applicationStage.getIcons().add(new Image("icon.png"));
    applicationStage.setScene(applicationScene);

    for(int i=0; i<10; i++) {
        Rectangle r = new Rectangle();
        r.setFill(Color.BLUE);
        r.setX(i * boxOuterSize);
        r.setY(0);
        r.setWidth(boxInnerSize);
        r.setHeight(boxInnerSize);
        r.setArcHeight(boxCornerRadius);
        r.setArcWidth(boxCornerRadius);
        r.setSmooth(true);
        rectangles[i] = r;
        root.getChildren().add(rectangles[i]);
    }

    container.getChildren().add(root);
    Button startButton = new Button("Start");
    startButton.setOnMouseClicked(new EventHandler<Event>() {
        @Override
        public void handle(Event arg0) {
            for(int i=0; i<10; i++) {
                rectangles[i].setFill(Color.RED);
                // TODO: some kind of scene refresh here
            }
        }
    });
    container.getChildren().add(startButton);

    applicationStage.show();
}

public static void main(String[] args) {
    launch(args);
}
}

最初所有的矩形都是蓝色的。我想在这里获得的行为是看到矩形按顺序改变颜色。问题是我只能看到最终结果(所有矩形同时改变颜色)。

Initially all the rectangles are blue. The behavior I want to obtain here is to see the rectangles changing colors sequentially. The problem is that I only get to see the end result (all the rectangles change their color at the same time).

推荐答案

这是一个老问题,它引起了我的注意,因为这是JavaFX新手所面临的一个非常普遍的问题。

This is an old question and it caught my eye since this is a very general issue faced by people new to JavaFX.

OP面临的问题是因为他更新所有问题矩形一下子,没有等待。

The problem that OP is facing is because he updates all the rectangles at once, without waiting.

OP可以等待创建一个新的线程,在循环的每次迭代中让线程处于休眠状态估计的秒数,然后在JavaFX上更新矩形的颜色应用程序线程使用 Platform.runLater

OP can wait by either creating a new Thread, put the thread on sleep for an estimated seconds for every iteration of the loop and then update the color of the rectangle on JavaFX application thread by using Platform.runLater.

@Override
public void handle(Event arg0) {
  new Thread(() -> {
     for(int i=0; i<10; i++) {
       try {
          Thread.sleep(1000); // Wait for 1 sec before updating the color
       } catch (InterruptedException e) {
          e.printStackTrace();
       }
       int finalI = i;
       Platform.runLater(() -> rectangles[finalI].setFill(Color.RED));// Update on JavaFX Application Thread
   }
}).start();

上述代码段更像是一种传统的做事方式。如果我们想使用JavaFX做事方式,我们可以通过使用动画来实现相同目的。

The above snippet is more of a traditional way of doing things. If we want to use the "JavaFX" ways of doing things, we can achieve the same by using an Animation.

下面是一段代码片段,它会在更改矩形的颜色之前等待 x-seconds 。它不需要任何额外的线程,因为等待是由每个矩形的 PauseTransition 处理的。

Below is a code snippet which will wait for x-seconds before changing the color of the rectangle. It doesn't need any extra thread since the wait is handled by PauseTransition applied for each rectangle.

startButton.setOnMouseClicked(new EventHandler<Event>() {
    @Override
    public void handle(Event arg0) {
        for(int i=0; i<10; i++) {
            PauseTransition pauseTransition = new PauseTransition(Duration.seconds(i));
            int finalI = i;
            pauseTransition.setOnFinished(event -> rectangles[finalI].setFill(Color.RED));
            pauseTransition.play();
        }
    }
});

它为每个矩形创建一个PauseTransition,并根据其在数组中的索引矩形,它会在更新颜色之前等待相同的秒数。

It creates a PauseTransition for each rectangle and depending on its index in the array rectangles, it waits for the same number of seconds before updating the color.

这篇关于如何强制Java FX场景刷新?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆