web-dev-qa-db-fra.com

Accéder à la classe de contrôleur FXML

Je souhaite communiquer à tout moment avec une classe de contrôleur FXML afin de mettre à jour les informations affichées à l'écran à partir de l'application principale ou d'autres étapes.

Est-ce possible? Je n'ai trouvé aucun moyen de le faire.

Les fonctions statiques peuvent constituer un moyen, mais elles n’ont pas accès aux contrôles du formulaire.

Des idées?

57
betaman

Vous pouvez obtenir le contrôleur à partir du FXMLLoader

FXMLLoader fxmlLoader = new FXMLLoader();
Pane p = fxmlLoader.load(getClass().getResource("foo.fxml").openStream());
FooController fooController = (FooController) fxmlLoader.getController();

stockez-le dans votre scène principale et fournissez la méthode getFooController () getter.
Dans les autres classes ou étapes, chaque fois que vous devez actualiser la page "foo.fxml" chargée, demandez-la à son contrôleur:

getFooController().updatePage(strData);

updatePage () peut être quelque chose comme:

// ...
@FXML private Label lblData;
// ...
public void updatePage(String data){
    lblData.setText(data);
}
// ...

dans la classe FooController.
De cette façon, les autres utilisateurs de la page ne se soucient pas de la structure interne de la page, comme quoi et où Label lblData est.

Regardez aussi le https://stackoverflow.com/a/10718683/682495 . Dans JavaFX 2.2, FXMLLoader est amélioré.

96
Uluk Biy

Juste pour aider à clarifier la réponse acceptée et peut-être gagner un peu de temps pour les nouveaux utilisateurs de JavaFX:

Pour une application JavaFX FXML, NetBeans générera automatiquement votre méthode de démarrage dans la classe principale comme suit:

@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
}

Maintenant, tout ce que nous avons à faire pour accéder à la classe du contrôleur est de changer la méthode FXMLLoader load() de l'implémentation statique à une implémentation instanciée, puis d'utiliser la méthode de l'instance pour obtenir le contrôleur, comme ceci :

//Static global variable for the controller (where MyController is the name of your controller class
static MyController myControllerHandle;

@Override
public void start(Stage stage) throws Exception {
    //Set up instance instead of using static load() method
    FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
    Parent root = loader.load();

    //Now we have access to getController() through the instance... don't forget the type cast
    myControllerHandle = (MyController)loader.getController();

    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
}
17
DatuPuti

Une autre solution consiste à configurer le contrôleur à partir de votre classe de contrôleur, comme suit ...

public class Controller implements javafx.fxml.Initializable {

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // Implementing the Initializable interface means that this method
        // will be called when the controller instance is created
        App.setController(this);
    }

}

C’est la solution que je préfère utiliser car le code est un peu compliqué à créer une instance entièrement fonctionnelle de FXMLLoader qui gère correctement les ressources locales, etc.

@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("/sample.fxml"));
}

versus

@Override
public void start(Stage stage) throws Exception {
    URL location = getClass().getResource("/sample.fxml");
    FXMLLoader loader = createFXMLLoader(location);
    Parent root = loader.load(location.openStream());
}

public FXMLLoader createFXMLLoader(URL location) {
    return new FXMLLoader(location, null, new JavaFXBuilderFactory(), null, Charset.forName(FXMLLoader.DEFAULT_CHARSET_NAME));
}
7
Caleb

Sur le chargement de l'objet à partir de l'écran principal, un moyen de transmettre les données que j'ai trouvées et fonctionnelles consiste à utiliser la recherche, puis à définir les données dans une étiquette invisible que je peux extraire ultérieurement de la classe de contrôleur. Comme ça:

Parent root = FXMLLoader.load(me.getClass().getResource("Form.fxml"));
Label lblData = (Label) root.lookup("#lblData");
if (lblData!=null) lblData.setText(strData); 

Cela fonctionne, mais il doit y avoir un meilleur moyen.

2
betaman