首页 > 解决方案 > 如何在 JavaFX 中异步显示从左到右移动的文本?

问题描述

我正在使用 JavaFX 做一个小游戏。我需要显示从“words.txt”读取的文本并从左到右为它们设置动画。我可以做同样的事情,但它们都同时出现。我希望延迟添加它们(例如 Thread.sleep()),但我不知道如何使用 JavaFX 做到这一点。

这是我的GameView.java

package views;

import java.util.Random;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;

import javafx.animation.AnimationTimer;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import models.InfoLabel;

public class GameView {

    // Declare final properties as private.
    private static final int GAME_WIDTH = 800;
    private static final int GAME_HEIGHT = 600;
    private static final String BACKGROUND_IMAGE = "/deep_blue.png";

    // Main game properties.
    private AnchorPane gamePane;
    private Scene gameScene;
    private Stage gameStage;
    private AnimationTimer gameTimer;

    private Stage menuStage;
    private int angle;

    private GridPane gridPane1;
    private GridPane gridPane2;

    private InfoLabel infoLabel;
    private Text text1;
    private Text[] texts;
    private ArrayList<String> words;

    Random positionGenerator;

    public GameView() {
        intializeStage();
        positionGenerator = new Random();
    }

    private void intializeStage() {
        loadWords();
        gamePane = new AnchorPane();
        gameScene = new Scene(gamePane, GAME_WIDTH, GAME_HEIGHT);
        gameStage = new Stage();
        gameStage.setScene(gameScene);
    }

    private void loadWords() {
        words = new ArrayList<>();
        BufferedReader br;
        try {
            br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/words.txt"), "UTF-8"));

            while (br.ready()) {
                words.add(br.readLine());
            }
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Collections.shuffle(words);
    }

    // Helper function to close the menu stage and show up the
    // game stage. Here, we need to re-define everything.
    public void createGame(Stage menuStage) {
        this.menuStage = menuStage;
        this.menuStage.hide();
        createBackground();
        createGame();
        createGameLoop();
        gameStage.show();
    }

    private void createGame() {
        text1 = new Text("Hello, World");
        text1.setFont(Font.font(16));
        text1.setFill(Color.WHITE);
        setNewElementPosition(text1);
        gamePane.getChildren().add(text1);

        // This is how I add the text components
        texts = new Text[words.size()];
        for (int i = 0; i < texts.length; i++) {
            texts[i] = new Text(words.get(i));
            texts[i].setFont(Font.font(16));
            texts[i].setFill(Color.WHITE);
            setNewElementPosition(texts[i]);
            gamePane.getChildren().add(texts[i]);
        }

        infoLabel = new InfoLabel("POINTS: 00");
        infoLabel.setLayoutX(650);
        infoLabel.setLayoutY(20);

        gamePane.getChildren().add(infoLabel);
    }

    private void setNewElementPosition(Text text) {
        text.setLayoutX(-positionGenerator.nextInt(1000));
        text.setLayoutY(positionGenerator.nextInt(400) + 100);
    }

    private void createBackground() {
        gridPane1 = new GridPane();
        gridPane2 = new GridPane();

        for (int i = 0; i < 12; i++) {
            ImageView backgroundImage1 = new ImageView(BACKGROUND_IMAGE);
            ImageView backgroundImage2 = new ImageView(BACKGROUND_IMAGE);

            GridPane.setConstraints(backgroundImage1, i / 3, i % 3);
            GridPane.setConstraints(backgroundImage2, i / 3, i % 3);

            gridPane1.getChildren().add(backgroundImage1);
            gridPane2.getChildren().add(backgroundImage2);
        }

        gridPane2.setLayoutX(-1024);
        gamePane.getChildren().addAll(gridPane1, gridPane2);
    }

    private void moveBackground() {
        gridPane1.setLayoutX(gridPane1.getLayoutX() + 1);
        gridPane2.setLayoutX(gridPane2.getLayoutX() + 1);

        if (gridPane1.getLayoutX() >= 1024) {
            gridPane1.setLayoutX(-1024);
        }

        if (gridPane2.getLayoutX() >= 1024) {
            gridPane2.setLayoutX(-1024);
        }
    }

    private void moveGameElement() {
        text1.setLayoutX(text1.getLayoutX() + 5);

        if (text1.getLayoutX() >= 1024) {
            text1.setLayoutX(-1024);
            text1.setLayoutY(positionGenerator.nextInt(400));
        }

        for (int i = 0; i < texts.length; i++) {
            texts[i].setLayoutX(texts[i].getLayoutX() + 5);
        }
    }

    private void createGameLoop() {
        gameTimer = new AnimationTimer() {

            @Override
            public void handle(long now) {
                moveBackground();
                moveGameElement();
            }
        };

        gameTimer.start();
    }
}

源代码可以在这里找到:https ://github.com/richardnguyen99/type-racing

我运行它的方式(块代码中的注释)是使用 for 循环并将所有单词映射到 JavaFX 中的文本组件。它的问题是加载时间非常长,并且单词同时出现并且它们相互碰撞。那么有什么办法像我的问题一样吗?另外,如果您可以就您在我的代码库中找到的其他内容给我一些建议并想要更正它,请告诉我。

谢谢!

标签: javamavenjavafx

解决方案


推荐阅读