将场景从 FXML 切换到纯 JavaFX UI class

Switch scenes from FXML to pure JavaFX UI class

我是 JavaFX 的新手。我已经学会了如何在 FXML 文件或 classes 之间切换场景,这些文件仅用 JavaFX 纯编码。 我现在最大的挑战是在 FXML UI 和另一个内置 JavaFX 之间切换,反之亦然,所以我知道这是可能的,但我就是做不好。我的应用程序控制器代码是:

package com.example.fxmltojavafx;

import com.sun.javafx.stage.EmbeddedWindow;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.stage.Stage;

import java.net.URL;
import java.util.ResourceBundle;

public class HelloController extends Application {
    @FXML
    private Label welcomeText;


    @FXML
    private Button bt_switch;

    @FXML
    protected void onHelloButtonClick() {

        //switch scene method from fxml to pure javafx
        //bt_switch.setOnAction(e -> window.setScene(InterfaceSwitch));
        welcomeText.setText("Welcome to JavaFX Application!");
    }

    @Override
    public void start(Stage stage) throws Exception {
        bt_switch.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                bt_switch.setOnAction(e -> window.setScene(InterfaceSwitch));
            }
        });
    }
}

如何引用我想通过单击 fxml 按钮加载的 JavaFX class?我试过 window.setScene(),但我的参考文献不正确。当然我不能使用 FMXMLLoader.load().

我想从此按钮加载的场景编码在此class: (编码到其中的按钮只是一个测试)

package com.example.fxmltojavafx;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

/***
 * Intefaccia puramente in JavaFX
 */
public class InterfaceSwitch extends Application {
    private Stage stage;
    @Override
    public void start(Stage stageInterface) throws Exception {
        VBox parent = new VBox();
        parent.getChildren().add(new Label("SERVER DOMINATOR : Inserisci dati"));
        //setup process
        HBox username = new HBox(new Label("username :")); //username field
        TextField usernametext = new TextField();
        username.getChildren().add(usernametext);
        parent.getChildren().add(username);

        HBox password = new HBox(new Label("password :")); //password field
        TextField passwordtext = new TextField();
        password.getChildren().add(passwordtext);
        parent.getChildren().add(password);

        HBox port = new HBox(new Label("port :")); //port field
        TextField porttext = new TextField();
        port.getChildren().add(porttext);
        parent.getChildren().add(port);

        HBox signupQuest = new HBox(new Label("Set up my game!"));
        parent.getChildren().add(signupQuest);

        Button button1 = new Button("Set up");
        parent.getChildren().add(button1);

        //Scene scene = new Scene(new Label("Server Dominator : Set up"));
        stage.setScene(new Scene(parent));
        stage.show();
    }
}

我的 FXML UI 基本上只有 2 个按钮,一个用于“hello world”,另一个是 bt_switch

我的主要class:

package com.example.fxmltojavafx;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 320, 240);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

这一定是一个简单的设置问题,但我无法理解它。我该怎么做?

Application class 代表整个应用程序,特别是它的生命周期。其目的是通过 start()init()stop() 等方法管理应用程序的启动和关闭。因此,每个应用程序应该只有一个 Application subclass 并且应该只有一个它的实例(在应用程序启动时为您创建)。

在您发布的代码中,HelloApplication 表示应用程序生命周期。 HelloController 只是一个控制器,不应该是 Application 的子 class。 InterfaceSwitch也不代表应用(它只是代表一个UI),所以它不应该是Application.

的subclass

你应该有类似的东西

public class SomeUI {

    private VBox root ;

    public SomeUI() {
        root = new VBox();
        root.getChildren().add(new Label("SERVER DOMINATOR : Inserisci dati"));
        //setup process
        HBox username = new HBox(new Label("username :")); //username field
        TextField usernametext = new TextField();
        username.getChildren().add(usernametext);
        root.getChildren().add(username);

        HBox password = new HBox(new Label("password :")); //password field
        TextField passwordtext = new TextField();
        password.getChildren().add(passwordtext);
        root.getChildren().add(password);

        HBox port = new HBox(new Label("port :")); //port field
        TextField porttext = new TextField();
        port.getChildren().add(porttext);
        root.getChildren().add(port);

        HBox signupQuest = new HBox(new Label("Set up my game!"));
        root.getChildren().add(signupQuest);

        Button button1 = new Button("Set up");
        root.getChildren().add(button1);

    }

    public Parent getRoot() {
        return root ;
    }
}

既然你说你的控制器是一个带有两个按钮的 FXML 文件的控制器,它需要两个事件处理程序方法(每个按钮一个)。切换场景的按钮的处理程序只是以正常方式执行此操作。显然,控制器不应该是 Application.

public class HelloController  {

   @FXML
   private Label welcomeText;


   @FXML
   protected void onHelloButtonClick() {
       welcomeText.setText("Welcome to JavaFX Application!");
   }

   @FXML
   protected void switchScenes() {
       SomeUI newScene = new SomeUI();
       Parent root = newScene.getRoot();
       welcomeText.getScene().setRoot(root);
   }

}

FXML 类似于:

<VBox spacing="10" xmlns = "http://javafx.com/javafx/16" xmlns:fx = "http://javafx.com/fxml/1" fx:controller="com.example.HelloController">

    <Label fx:id="welcomeText" />
    <Button text="Say Hello" onAction="#onHelloButtonClick"/>
    <Button text="Switch scenes" onAction="#switchScenes" />

</VBox>