web-dev-qa-db-fra.com

JavaFX: transmettre des paramètres lors de l'instanciation d'une classe de contrôleur

Je travaille actuellement sur l'application JavaFX. Tout mon interface graphique est en .fxml format et via la classe de contrôleur gère tous les composants de l'interface graphique. Cependant, j'ai des difficultés à instancier la classe de contrôleur avant de charger le chargeur FXML. Je n'ai pas pu trouver une bonne solution pour ma question des autres sur stackoverflow, donc ce n'est pas une question en double.

La raison pour laquelle j'instancie la classe de contrôleur est que je veux passer certains paramètres pour que ces paramètres soient affichés dans GUI.

Je charge un fichier FXML de la manière suivante:

/*
 * 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();
}

Et voici ma classe de contrôleur actuelle:

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

Et je reçois cette exception:

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

Les deux façons les plus simples de le faire pour les petites applications sont les suivantes:

  1. Ne spécifiez pas le fx:controller Dans le fxml. Créez une instance de contrôleur en lui transmettant des données, puis passez-la au FXMLLoader.

  2. Spécifiez le fx:controller Dans le fxml. Récupérez l'instance de contrôleur à partir de FXMLLoader et transmettez les données au contrôleur.

Voici les exemples des deux types ci-dessus. Chacun des exemples a 3 composants:

  • FXML - Le fichier FXML, qui doesn't have La déclaration fx:controller Pour le premier type et l'a pour le deuxième type.
  • Contrôleur - A un constructor pour le premier type. A setter methods Pour le deuxième type.
  • Principal - Utilisé pour charger FXML et transmettre des données au contrôleur. Pour le premier cas, il sets the controller to FXMLLoader. En seconde, c'est fetches the controller from the FXMLLoader.

1. Créez une instance de contrôleur manuellement

FXML - Ne spécifiez pas le 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 - créer un constructeur pour accepter les valeurs par défaut

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

Main - Créez une instance de Controller, en lui passant de la valeur puis passez-la au 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. Récupérez une instance de contrôleur à partir de FXMLLoader

FXML - A spécifié le 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 - A des méthodes Setter pour accepter l'entrée

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 - Récupère l'instance de Controller à partir de FXMLLoader après avoir appelé la load() puis appelle les méthodes de définition pour transmettre les données.

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