簡體   English   中英

JavaFX 矩形不更新

[英]JavaFX rectangle doesn't update

我正在嘗試使用元胞自動機做一個迷宮解析器,但是對於自動機的每一代新一代網格都有一個顯示問題,我們嘗試以矩形的形式顯示單元格。初始化效果很好,並且顯示了網格,最后一代的模擬也顯示,但不顯示中間步驟。

第一代圖片

上一代

//Initialise la liste des rectangles
    public void initRectList() {

            for(int height = 0; height < this.mazeA.grid.getHeight(); height++) {
                for(int width = 0; width < this.mazeA.grid.getWidth(); width++) {

                this.rectList[height][width] = new Rectangle(REC_HEIGHT,REC_WIDTH, getColorCell(this.mazeA.grid, height, width));
            }
        }
    }

    //Dessine le labyrinthe
    public void drawGrid() {

        for (int height = 0; height < this.mazeA.grid.getHeight(); height++) {
            for(int width = 0; width < this.mazeA.grid.getWidth(); width++) {

                tilePane.getChildren().add(this.rectList[height][width]);

            }
        }
    }
public class MazeFX  {

    private HBox root = new HBox();
    private Scene scene = new Scene(root,1100,800);
    private TilePane tilePane = new TilePane();
    private Grid grid = new Grid(30,30);

    private Rectangle[][] rectList = new Rectangle[30][30];

    private VBox buttons = new VBox();
    private Button reset = new Button("Reset");
    private Button pas = new Button("Play");
    private Button load = new Button("Load");

    private MazeAutomaton mazeA;

    private final double REC_HEIGHT = 20.;
    private final double REC_WIDTH = 20.;


    public MazeFX(Stage stage) throws InterruptedException {

        scene.getStylesheets().add(getClass().getResource("/src/application.css").toExternalForm());
        initButton();
        initLayout();

        initGridByTopologie();

        mazeA = new MazeAutomaton(this.grid);

        initRectList();
        drawGrid();



        pressedButtons(stage);
        setWindow(stage);

        displayWindow(stage);

    }

開始下一代你按下一個按鈕。

//Action de l'utilisateur sur l'un des bouttons
    public void pressedButtons(Stage stage) {
        pressReset();
        pressPAS();
        pressLoad(stage);
    }

   //Boutton Play/Stop préssé
    public void pressPAS() {

        this.pas.setOnMouseClicked(e -> {
            for (int i = 0; i < 30; i++) {

                mazeA.nextStep();

                try {
                    Thread.sleep(100);
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }
                updateRectColor();

            }
                }
        );
    }

問題似乎是我們被困在方法 setOnMouseClicked() 並且矩形的更新沒有完成,通過文本顯示我看到了自動機的演變,這表明我們模擬有效並且問題似乎來自 JavaFX

JavaFX 應用程序線程作為循環運行。 實際上(實際的實現細節要復雜得多)該循環執行以下操作(在偽代碼中):

while (applicationIsRunning()) {
    if (thereAreEventsToHandle()) {
        handleEvents();
    }
    if (thereAreAnimationsToUpdate()) {
        updateAnimations();
    }
    if (itsTimeToRenderTheScene()) {
        renderScene();
    }
}

默認情況下,JavaFX 每秒最多渲染場景 60 次。

事件處理程序中的代碼在 FX 應用程序線程上執行(由上面偽代碼循環中的第一個塊調用)。 由於它在該線程上休眠,因此在整個事件處理程序完成之前,FX 應用程序線程永遠不會到達循環的第三部分(渲染場景)。 因此,您永遠不會看到中間更新,因為場景永遠不會被渲染。

假設mazeA.nextStep()不會阻塞(或需要很長時間才能運行),最好將其重構為Animation ,例如Timeline

public void pressPAS() {

    this.pas.setOnMouseClicked(e -> {
        KeyFrame updateMaze = new KeyFrame(Duration.ZERO, evt -> mazeA.nextStep());
        KeyFrame updateRect = new KeyFrame(Duration.millis(100), evt -> updateRectColor());
        Timeline timeline = new Timeline(updateMaze, updateRect);
        timeline.setCycleCount(30);
        timeline.play();
    });
}

timeline.play()方法簡單地啟動 animation 並立即返回,允許 FX 應用程序線程繼續。 當 FX 應用程序線程檢查正在運行的動畫時,它會檢查是否該執行關鍵幀中的任一處理程序,如果是則執行它們。 然后它會像往常一樣渲染場景。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM