javafx - JavaFX:在实例化 Controller 类时传递参数

标签 javafx java-8

我现在正在研究JavaFX应用程序。我的所有GUI都是.fxml格式,并且通过 Controller 类管理所有GUI组件。但是,在加载FXML加载程序之前,我很难用实例化 Controller 类。我无法从其他关于stackoverflow的问题中找到一个好的解决方案,因此这不是重复的问题。

我实例化 Controller 类的原因是我想传递一些参数,以便这些参数将显示在GUI中。

我通过以下方式加载FXML文件:

/*
 * for Work Order button
 */
@FXML
private void pressWorkOrder() throws Exception{ 
    WorkOrderController wo = new WorkOrderController("ashdkjhsahd");    //instantiating constructor     

    Parent parent = FXMLLoader.load(getClass().getResource("/fxml/WorkOrder.fxml"));        
    Scene scene = new Scene(parent);
    Stage stage = new Stage();
    stage.setScene(scene);
    stage.setTitle("Word Order");
    stage.setResizable(false);
    stage.show();
}

这是我实际的Controller类:
public class WorkOrderController implements Initializable{

     @FXML
     private Button summary;
     private String m,n;

     public WorkOrderController(String str) {
         // TODO Auto-generated constructor stub
         m = str;
     }  

     //for testing
     public void set(String str){
         m = str;
     }  

     @FXML
     public void check(){
         System.out.println("Output after constructor was initialized " + m);
     }

     @Override
     public void initialize(URL location, ResourceBundle resources) {
        // TODO Auto-generated method stub
     }
 }

我得到这个异常:
at javafx.fxml.FXMLLoader.processStartElement(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.load(Unknown Source)
at MainController.pressWorkOrder(MainController.java:78)
... 57 more
Caused by: java.lang.InstantiationException: WorkOrderController
at java.lang.Class.newInstance(Unknown Source)
at sun.reflect.misc.ReflectUtil.newInstance(Unknown Source)
... 71 more
Caused by: java.lang.NoSuchMethodException: WorkOrderController.<init>()
at java.lang.Class.getConstructor0(Unknown Source)
... 73 more

最佳答案

对于小型应用程序,最简单的两种方法是:

  • 不要在fxml中指定fx:controller。通过将数据传递给它来创建一个 Controller 实例,然后将其传递给FXMLLoader。
  • 在fxml中指定fx:controller。从FXMLLoader获取 Controller 实例,然后将数据传递给 Controller ​​。

  • 以下是上述两种类型的示例。每个示例都有3个组成部分:
  • FXML-FXML文件,它对第一种类型的doesn't have声明进行fx:controller,对第二种类型进行声明。
  • Controller -第一种类型具有constructor。第二种类型具有setter methods
  • Main-用于加载FXML并将数据传递到 Controller 。对于第一种情况,它为sets the controller to FXMLLoader。在第二秒,它是fetches the controller from the FXMLLoader


  • 1.手动创建 Controller 实例

    FXML -不指定fx:controller
    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.layout.FlowPane?>
    <?import javafx.scene.control.Label?>
    
    <FlowPane fx:id="root" xmlns:fx="http://javafx.com/fxml">
        <children>
            <Label fx:id="firstName" text="" />
            <Label fx:id="lastName" text="" />
        </children>
    </FlowPane>
    

    Controller -创建一个构造函数以接受默认值
    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.property.StringProperty;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Label;
    
    import java.net.URL;
    import java.util.ResourceBundle;
    
    public class SampleController implements Initializable {
    
        private StringProperty firstNameString = new SimpleStringProperty();
        private StringProperty lastNameString = new SimpleStringProperty();
    
        /**
         * Accepts the firstName, lastName and stores them to specific instance variables
         * 
         * @param firstName
         * @param lastName
         */
        public SampleController(String firstName, String lastName) {
            firstNameString.set(firstName);
            lastNameString.set(lastName);
        }
    
        @FXML
        Label firstName;
    
        @FXML
        Label lastName;
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
            firstName.setText(firstNameString.get());
            lastName.setText(lastNameString.get());
        }
    }
    

    -创建一个Controller实例,方法是将值传递给它,然后将其传递给FXMLLoader
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Scene;
    import javafx.scene.layout.FlowPane;
    import javafx.stage.Stage;
    
    public class Main extends Application {
        @Override
        public void start(Stage primaryStage) throws Exception {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Sample.fxml"));
    
            // Create a controller instance
            SampleController controller = new SampleController("itachi", "uchiha");
            // Set it in the FXMLLoader
            loader.setController(controller);
            FlowPane flowPane = loader.load();
            Scene scene = new Scene(flowPane, 200, 200);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    2.从FXMLLoader获取 Controller 实例

    FXML -已指定fx:controller
    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.layout.FlowPane?>
    <?import javafx.scene.control.Label?>
    
    <!-- Controller Specified -->
    <FlowPane fx:id="root" xmlns:fx="http://javafx.com/fxml" fx:controller="SampleController">
        <children>
            <Label fx:id="firstName" text="" />
            <Label fx:id="lastName" text="" />
        </children>
    </FlowPane>
    

    Controller -具有Setter方法来接受输入
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Label;
    
    import java.net.URL;
    import java.util.ResourceBundle;
    
    public class SampleController implements Initializable {
    
        @FXML
        Label firstName;
    
        @FXML
        Label lastName;
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
    
        }
    
        /**
         * Accepts a String and sets it to the firstName Label
         *
         * @param firstNameString
         */
        public void setFirstName(String firstNameString) {
            firstName.setText(firstNameString);
        }
    
        /**
         * Accepts a String and sets it to the lastName Label
         *
         * @param lastNameString
         */
        public void setLastName(String lastNameString) {
            lastName.setText(lastNameString);
        }
    }
    

    主要-调用load()之后从FXMLLoader获取Controller实例,然后调用setter方法以传递数据。
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Scene;
    import javafx.scene.layout.FlowPane;
    import javafx.stage.Stage;
    
    public class Main extends Application {
        @Override
        public void start(Stage primaryStage) throws Exception {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Sample.fxml"));
            FlowPane flowPane = loader.load();
            // Get the Controller from the FXMLLoader
            SampleController controller = loader.getController();
            // Set data in the controller
            controller.setFirstName("itachi");
            controller.setLastName("uchiha");
            Scene scene = new Scene(flowPane, 200, 200);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    关于javafx - JavaFX:在实例化 Controller 类时传递参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30814258/

    相关文章:

    javafx - JavaFX 中的堆叠图表

    java - javafx中如何使背景大小适合窗口大小?

    java - 我需要在Java中获取二维数组对象的索引

    java - 如何获取 JAR 文件中资源目录中的所有资源?

    java 8中的字符串占用内存较少

    java - 参数返回 void 的可调用/可运行/函数?

    java - 如何设置 JavaFX XYChart 中节点之间的间隙

    xml - 如何在 FXML 文件中使用 java 变量?

    未找到 Java 8 总和和总数

    java - ArrayList 包含来自另一个 ArrayList 的一个或多个实体