当我使用 while 循环时 JavaFX 程序没有启动

标签 java css user-interface intellij-idea javafx

好的,所以我正在尝试使用 JavaFX 制作带有 GUI 的基于文本的游戏。在我进入实际的游戏循环之前,一切都运行良好。尽管一旦我将代码放入游戏循环中,程序就无法启动。它会无错误或异常地运行,但窗口根本不会弹出。当我关闭窗口时,IntelliJ 中的所有命令行都显示“进程已完成,退出代码为 130”,这显然意味着程序已关闭,因为用户按下 Ctrl+C。事实并非如此,因为窗口甚至没有弹出,所以任何用户都不可能单击 Ctrl+C 来终止程序。所以我的问题是我能做些什么才能用游戏循环(while 循环)运行我的程序,而窗口不会拒绝弹出。这是我的代码:

package sample;
/**
 * Created by Angel on 7/26/16.
 */

import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;

public class Game {

    // Inventory is a class that i made,
    // but im sure it has nothing to do with my problem
    private Inventory inv = new Inventory();
    private String levels;

    private Scene scene;
    private Label topText;
    private Button btn1;
    private Button btn2;
    private Button btn3;
    private boolean gameOn;

    public void gameStart(){

        // Setting the GUI

        // Setting up the window
        VBox window = new VBox(210);

        // setting up the top text holder.
        HBox textHolder = new HBox();
        textHolder.setAlignment(Pos.CENTER);

        // setting up the label
        topText = new Label();
        topText.setText("You in a dark room, what do you do?");

        // setting up the button holder
        HBox buttonHolder = new HBox(50);
        buttonHolder.setAlignment(Pos.CENTER);

        // setting up the buttons
        btn1 = new Button();
        btn1.setPrefWidth(260);
        btn1.setPrefHeight(30);
        btn1.getStyleClass().add("gameButtons");
        btn1.setText("1");

        btn2 = new Button();
        btn2.setPrefWidth(260);
        btn2.setPrefHeight(30);
        btn2.getStyleClass().add("gameButtons");
        btn2.setText("2");

        btn3 = new Button();
        btn3.setPrefWidth(260);
        btn3.setPrefHeight(30);
        btn3.getStyleClass().add("gameButtons");
        btn3.setText("3");


        // finalizing the gui, by putting it all together
        textHolder.getChildren().add(topText);
        buttonHolder.getChildren().addAll(btn1, btn2, btn3);
        window.getChildren().addAll(textHolder, buttonHolder);

        // setting up the scene
        scene = new Scene(window, 800, 600);

        //adding the css script
        // adding css script
        scene.getStylesheets().add(this.getClass().getResource("game.css").toExternalForm());

        // the game loop.

        levels = "Storyline";
        gameOn = true;
        while(gameOn) {
            switch (levels) {
                case "Storyline":
                    btn1.setText("search around");
                    btn2.setText("turn the light on");
                    btn3.setText("stand in fear");

                    btn2.setOnAction(e -> levels = "level1");
                    break;
                case "level1":
                    topText.setText("You turned the light on");
                    break;
            }
        }

    }

    public Scene getScene(){
        return scene;
    }

}

最佳答案

这不应该是一个游戏循环。单击按钮会触发一个事件。应该在那里处理。没有必要一次又一次地更新按钮文本等,这正是您目前正在做的。

通过在此处执行循环,您会阻塞应用程序线程,该线程负责重绘和处理用户交互,使其无法执行任务。

重构您的代码以基于事件工作,即

用户交互(单击按钮)触发 ui 更新(状态更改和 UI 的单次更新)。

例如像这样:

public class Game {

    ...

    public void gameStart(){

        ...

        // setting up the scene
        scene = new Scene(window, 800, 600);

        // adding css
        scene.getStylesheets().add(this.getClass().getResource("game.css").toExternalForm());

        setLevel("Storyline");
    }

    public void setLevel(String newLevel) {
         // TODO: integrate gameOn value
         if (newLevel != null && !newLevel.equals(levels)) {
              levels = newLevel;
              switch (levels) {
                case "Storyline":
                    btn1.setText("search around");
                    btn2.setText("turn the light on");
                    btn3.setText("stand in fear");

                    // user interaction triggers setting the level
                    btn2.setOnAction(e -> setLevel("level1"));
                    break;
                case "level1":
                    topText.setText("You turned the light on");
                    break;
            }
         }
    }

    ...

}

附加建议:不要将级别表示为 String,将其表示为实现接口(interface)的实例:

public interface Level {
     // do updates for level start on game
     void updateGameLevelStart(Game game);

     // cleanup code e.g. unregistering event handlers...
     void updateGameLevelEnd(Game game);
}

这将允许您将 levels 的类型更改为 Level 并简化更新:

public void setLevel(Level newLevel) {
     if (!Objects.equals(levels, newLevel)) {
         if (levels != null) {
              // cleanup old level
              levels.updateGameLevelEnd(this);
         }
         levels = newLevel;
         if (newLevel != null) {
              // start new level
              newLevel.updateGameLevelStart(this);
         }
     }
}

这当然需要您使 ui 的相关部分可供 Level 实现访问。

关于当我使用 while 循环时 JavaFX 程序没有启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38627860/

相关文章:

jquery-ui - jQuery UI 与 Scriptaculous?

user-interface - 备用 Perforce 客户端?

java - 如果您只是设置和获取值,使用 AtomicLong 有什么优势吗?

java - 配置失败: @AfterMethod tearDown

打印海报的 HTML 和 CSS

css - 文本框的 MVC4 图形验证

javascript - HTML/Jquery : div not detecting hover even when z-index set to highest?

java - 填充颜​​色自定义形状Java

java - JPA 不使用 Converter 类更新列

user-interface - 如何删除 GTK 中条目和 TextView 中插入的表情符号?