【问题标题】:JavaFX program not starting when I use a while loop当我使用 while 循环时 JavaFX 程序没有启动
【发布时间】:2016-12-02 08:14:54
【问题描述】:

好的,所以我正在尝试使用 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;
    }

}

【问题讨论】:

  • 你为什么要使用一个不断设置文本的无限循环?
  • 天哪,我什至没有意识到我正在这样做。还有其他方法吗?我不知道该怎么做……没有循环就不会写错了吗?还是非常规的方式?我正在尝试使用 switch 语句。有没有其他方法可以返回并再次运行 switch 语句,而不使用循环?@krzyk
  • @AngelGarcia 使用方法和对象。
  • JavaFX 不是一直打开场景窗口而无需使用任何循环吗?

标签: java css user-interface intellij-idea javafx


【解决方案1】:

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

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

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

用户交互(按钮点击)触发 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,将其表示为实现接口的实例:

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

这当然需要您让Level 实现可以访问用户界面的相关部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-19
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 2020-07-17
    • 1970-01-01
    相关资源
    最近更新 更多