简体   繁体   English

如何强制Java FX场景刷新?

[英]How to force Java FX scene refresh?

I have an Java FX scene with a start button and several rectangles which represent the tiles of a map. 我有一个带有开始按钮的Java FX场景和几个代表地图图块的矩形。 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. 我还绘制了一个代表我的探险家的球体(它必须探索地图),但我在运行动画时遇到了困难。

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. 在我的OnMouseClicked开始按钮处理程序中,我启动了一个用于探索地图的算法,该算法更改了球体的位置和已访问过的切片的颜色。 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? 如何强制进行场景更新,以便按顺序查看所有颜色变化?

Later edit: 稍后编辑:

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). 问题是我只能看到最终结果(所有矩形同时改变它们的颜色)。

This is an old question and it caught my eye since this is a very general issue faced by people new to JavaFX. 这是一个老问题,它引起了我的注意,因为这是JavaFX新手面临的一个非常普遍的问题。

The problem that OP is facing is because he updates all the rectangles at once, without waiting. OP面临的问题是因为他一次更新所有矩形,无需等待。

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 . OP可以等待创建一个新的线程,在循环的每次迭代中将线程置于休眠状态估计的秒数,然后使用Platform.runLater更新JavaFX应用程序线程上的矩形颜色。

@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();

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 . 如果我们想要使用“JavaFX”做事方式,我们可以通过使用Animation来实现相同的目的。

Below is a code snippet which will wait for x-seconds before changing the color of the rectangle. 下面是一段代码片段,在更改矩形的颜色之前会等待x-seconds It doesn't need any extra thread since the wait is handled by PauseTransition applied for each rectangle. 它不需要任何额外的线程,因为等待是由为每个矩形应用的PauseTransition处理的。

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();
        }
    }
});

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. 它为每个矩形创建一个PauseTransition,并根据其在数组rectangles索引,在更新颜色之前等待相同的秒数。

This is because of : 这是因为:

exception : Test cannot be cast to javafx.event.EventHandler

Well, I have no idea how Class cast exception came up. 好吧,我不知道Class cast异常是怎么出现的。

Otherwise, to delay, you can use Thread.sleep() . 否则,要延迟,可以使用Thread.sleep()

UPDATE: 更新:

Its good to use AnimationTimer to create an animation, you don't need to refresh anything. 很好用AnimationTimer来创建动画,你不需要刷新任何东西。

Here, I have done a short EG to show color rect using FillTransition . 在这里,我做了一个简短的EG,使用FillTransition显示颜色rect。

CODE: 码:

import javafx.animation.FillTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;


public class NewFXMain1 extends Application {
private static final double boxOuterSize = 50;
private static final double boxInnerSize = 48;
private static final double boxCornerRadius = 20;
private Rectangle rectangles = new Rectangle();

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

@Override
public void start(Stage primaryStage) {
    primaryStage.setTitle("rect");


    Button btn = new Button();
    StackPane root = new StackPane();


    Rectangle r = new Rectangle();
    r.setFill(Color.BLUE);
    r.setX(2 * boxOuterSize);
    r.setY(0);
    r.setWidth(boxInnerSize);
    r.setHeight(boxInnerSize);
    r.setArcHeight(boxCornerRadius);
    r.setArcWidth(boxCornerRadius);
    r.setSmooth(true);
    r.localToScene(boxOuterSize, boxOuterSize);
    rectangles = r;

    root.getChildren().add(rectangles);

    btn.setText("display");
    btn.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
           FillTransition ft = new FillTransition(Duration.millis(3000), rectangles, Color.RED, Color.BLUE);
           ft.setCycleCount(4);
           ft.setAutoReverse(true);
           ft.play();
        }
    });

    root.getChildren().add(btn);
    primaryStage.setScene(new Scene(root, 300, 250));
    primaryStage.show();
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM