web-dev-qa-db-ja.com

JavaFX:コントローラークラスのインスタンス化中にパラメーターを渡す

私は現在JavaFXアプリケーションに取り組んでいます。私のGUIはすべて.fxmlフォーマットおよびコントローラークラスを介して、すべてのGUIコンポーネントを管理します。ただし、FXMLローダーをロードする前にコントローラークラスをインスタンス化するに問題があります。私はstackoverflowに関する他の人からの質問に対する良い解決策を見つけることができませんでした。したがって、これは重複した質問ではありません。

コントローラークラスをインスタンス化する理由は、いくつかのパラメーターを渡すにしたいので、これらのパラメーターが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
25
inson

小規模なアプリケーションで行う最も簡単な2つの方法は次のとおりです。

  1. Fxmlで_fx:controller_を指定しないでください。データを渡してコントローラーインスタンスを作成し、FXMLLoaderに渡します。

  2. Fxmlで_fx:controller_を指定します。 FXMLLoaderからコントローラーインスタンスを取得し、データをコントローラーに渡します。

以下は、上記の両方のタイプの例です。各例には3つのコンポーネントがあります。

  • FXML-FXMLファイル。最初のタイプの_doesn't have_宣言と_fx:controller_宣言であり、2番目のタイプの宣言です。
  • コントローラー-最初のタイプにconstructorがあります。 2番目のタイプには_setter methods_があります。
  • メイン-FXMLをロードし、コントローラーにデータを渡すために使用されます。最初の場合、それは_sets the controller to FXMLLoader_です。第二に、それは_fetches the controller from the FXMLLoader_です。

1.コントローラーインスタンスを手動で作成する

[〜#〜] 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());
    }
}
_

メイン-値を渡し、FXMLLoaderに渡すことで、Controllerインスタンスを作成します

_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からコントローラーインスタンスを取得する

[〜#〜] 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);
    }
}
_

Main-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);
    }
}
_
62
ItachiUchiha