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
Les deux façons les plus simples de le faire pour les petites applications sont les suivantes:
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.
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:
doesn't have
La déclaration fx:controller
Pour le premier type et l'a pour le deuxième type.constructor
pour le premier type. A setter methods
Pour le deuxième type.sets the controller to FXMLLoader
. En seconde, c'est fetches the controller from the FXMLLoader
.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);
}
}
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);
}
}