JavaFX 更新屏幕

JavaFX update screen

我试图在屏幕上显示迷宫生成的过程,但在过程完成之前屏幕永远不会更新。我正在使用消费者通知 JavaFX 方面。我尝试使用 Platform.runLater() 无济于事。

以下是正在使用的文件:

"你好-view.fxml"

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.StackPane?>
<StackPane onMouseClicked="#randomize" fx:id="sp" xmlns:fx="http://javafx.com/fxml" fx:controller="com.example.demo2.HelloController">
</StackPane>

这是迷宫生成器的 t运行 版本,“BasicMaze.java”:

package com.example.demo2;
import java.util.*;
import java.util.function.Consumer;

public class BasicMaze {
    public int width;
    public int height;

    private transient List<Consumer<BasicMaze>> consumers = new ArrayList<>();

    public void reset(int w, int h) {
        width = w;
        height = h;
        alertConsumers();
    }

    public void addConsumer(Consumer<BasicMaze> l) {
        if (consumers == null) consumers = new ArrayList<>();
        consumers.add(l);
    }

    public void alertConsumers() {
        consumers.forEach(c -> c.accept(this));
    }

    public void generate() {
        int slots = width * height;

        do {
            if (Math.random() * 10 < 1) {
                alertConsumers(); //Platform.runLater tried here
                slots--;
            }
        } while (slots > 1);
        System.out.println("DONE!");
    }
}

这是控制器,“HelloController.java”:

package com.example.demo2;

import javafx.fxml.FXML;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;

public class HelloController {
    @FXML
    StackPane sp;

    final Canvas canvas = new Canvas(250,250);
    BasicMaze maze = new BasicMaze();

    @FXML
    public void initialize() {
        sp.getChildren().add(canvas);
        maze.addConsumer(basicMaze -> this.draw()); //platform.runLater tried here.
    }

    public void randomize() {
        maze.reset(5, 5);
        maze.generate();
    }

    public void draw() {
        GraphicsContext gc = canvas.getGraphicsContext2D() ;
        gc.setLineWidth(1.0);
        gc.setFill(Color.BLACK);
        for (int j = 0; j < maze.height; j++) {
            for (int i = 0; i < maze.width; i++) {
                gc.moveTo(Math.random()*250, Math.random()*250);
                gc.lineTo(Math.random()*250, Math.random()*250);
                gc.stroke();
            }
        }

    }

}

这是主要函数存根:

package com.example.demo2;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 320, 240);
        stage.setScene(scene);
        stage.show();
    }

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

如果您 运行 并点击屏幕,“完成!”会出现在控制台上,会有卡顿,然后屏幕会出现一堆黑线。我正在尝试让屏幕随着每条线的绘制而更新。

好吧,这实际上非常简单(几乎没有带来不便!),这是我从 Sergey Grinev's posts 中得出的结论。所有需要改变的(几乎)是 运行 后台任务在它自己的线程上。

因此,我们将 maze.generate() 包装在一个线程中:

public void randomize() {
    maze.reset(500, 500);
    new Thread(maze::generate).start();
}

现在 运行稍后的初始化工作!

@FXML
public void initialize() {
    sp.getChildren().add(canvas);
    maze.addConsumer(basicMaze -> Platform.runLater(this::draw));
}

底层对象根本不需要改变。