简体   繁体   English

单击按钮时如何重新启动 JavaFX 应用程序

[英]How to restart a JavaFX application when a button is clicked

I went through almost every post here regarding the matter but most of them doesn't explain what to do properly.我浏览了这里几乎所有关于此事的帖子,但其中大部分都没有解释正确的做法。 To the question:对于这个问题:

I created a javaFX application, a dice game, human player vs. computer, but during any time while playing the game human player should be able to click button "new game" and what it should do is to restart the game from beginning.我创建了一个 javaFX 应用程序,一个骰子游戏,人类玩家与计算机,但在玩游戏的任何时候,人类玩家都应该能够点击“新游戏”按钮,它应该做的是从头开始重新启动游戏。

I tried relaunching the stage again but in javafx we cannot call the launch method twice.我尝试再次重新启动舞台,但在 javafx 中我们不能两次调用启动方法。

1)Is there a way i can implement this without restarting the whole application? 1)有没有一种方法可以在不重新启动整个应用程序的情况下实现它?

2)if not how can i restart the application completely using a button click? 2)如果不是,我如何使用按钮单击完全重新启动应用程序?

Main class主类

public class Main {
public static void main(String[] args) {
    GameUI gameUI = new GameUI();

    gameUI.launch(GameUI.class, args);

}   

GameUI (i removed many codes from this class to make it short. codes that i think enough to give an idea is included. sorry if it is too long.) GameUI(我从这个类中删除了许多代码以使其简短。包括我认为足以提供想法的代码。如果它太长,抱歉。)

public class GameUI extends Application  {

 //all btn and label declarations 
//creating instances for necessary classes

private Scene scene;

@Override
public void start(Stage primaryStage) throws Exception {

    //Displaying Dice for Player and Computer
    setLabelsPlyr(diesP);
    setLabels(diesC);

    btnThrow = new Button("Throw");
    btnThrow.setPrefSize(70, 40);

    //Throw action is performed
    btnThrow.setOnAction(e -> {

    //setting and displaying dies
      DieClass[] com = getNewDiceArrC();  
      lblDiceOneC.setGraphic(new ImageView(diesC[0].getDieImageC()));
      //so on.....

      DieClass[] playerAr = getNewDiceArrP();
      lblDiceOnePlyr.setGraphic(new ImageView(diesP[0].getDieImageP()));
      //so on...
    });

    btnNewGame = new Button("New Game");
    btnNewGame.setOnAction(e -> {

           **//WHAT TO DO HERE?????**

    });

    //setting layouts


    GridPane gridPane = new GridPane();
    gridPane.add(lblComputer, 0, 0);
    //so on.....

    Scene scene = new Scene(gridPane, 1100, 400);
    primaryStage.setScene(scene);
    primaryStage.setTitle("dice Game");
    primaryStage.show();

}

//some other methods
public void setLabels(DieClass[] dies) {
    for (int i=0; i < dies.length; i++) {
        lblDiceOneC = new Label();
        lblDiceOneC.setGraphic(new ImageView(dies[0].getDieImageC()));
        ++i;
       //so on.....

        break;
    }
}

public void setLabelsPlyr(DieClass[] dies){
    for (int i=0; i<dies.length; i++) {
        lblDiceOnePlyr = new Label();
        lblDiceOnePlyr.setGraphic(new ImageView(dies[0].getDieImageP()));
        ++i;
        lblDiceTwoPlyr = new Label();
        //so on......
        break;
    }
}

ps I am very new to JavaFX and somewhat new to java programming. ps 我对 JavaFX 很陌生,对 Java 编程也有些陌生。

You already noticed that you cannot do the launching process again.您已经注意到您无法再次执行启动过程。 Therefore your best option is to rewrite the application class and move the initialisation logic to a new method:因此,您最好的选择是重写应用程序类并将初始化逻辑移至新方法:

void cleanup() {
    // stop animations reset model ect.
}

void startGame(Stage stage) {
    // initialisation from start method goes here

    btnNewGame.setOnAction(e -> {
       restart(stage);
    });

    stage.show();
}

void restart(Stage stage) {
    cleanup();
    startGame(stage);
}

@Override
public void start(Stage primaryStage) {
    startGame(primaryStage);
}

Notes笔记

  • Depending on the parts of the scene changed, it may be enough to change the state of some of the nodes (more efficient than creating a new scene).根据场景的变化部分,改变一些节点的状态可能就足够了(比创建新场景更有效)。 (Just take a look at the changes you made during the game and decide for yourself) (看看你在游戏中所做的改变,然后自己决定)
  • launch() is a static method and you should not create a instance of your application class yourself for that reason. launch()是一个static方法,因此您不应该自己创建应用程序类的实例。 Use Application.launch(GameUI.class, args);使用Application.launch(GameUI.class, args); instead and let the method handle the creation of the GameUI instance.相反,让该方法处理GameUI实例的创建。
  • It may be a better design to move the UI creation to a class different to the application class.将 UI 创建移动到与应用程序类不同的类可能是更好的设计。 This way reuse of the code is easier, since it does not require the creation of a instance of a subclass of Application .这种代码的重用方式更容易,因为它不需要创建Application的子类的实例。

In your Start() function, add the following line:在您的Start()函数中,添加以下行:

Platform.setImplicitExit(false);

This will make your application run in background without exiting.这将使您的应用程序在后台运行而不会退出。

Now, use a wrapper function to start the second time, say:现在,使用包装函数第二次启动,比如:

void displayApplication() {
         Platform.runLater(new Runnable() {
            @Override
            public void run() {
                try {
                    start(new Stage());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

what should be the code in the clean up(). cleanup()中的代码应该是什么。 Only having Platform.exit() is not working for me. 仅具有Platform.exit()对我不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM