Comment passer des paramètres à une fenêtre secondaire dans javafx? Existe-t-il un moyen de communiquer avec le contrôleur correspondant?
Par exemple: L'utilisateur choisit un client dans un TableView
et une nouvelle fenêtre s'ouvre, affichant les informations du client.
Stage newStage = new Stage();
try
{
AnchorPane page = (AnchorPane) FXMLLoader.load(HectorGestion.class.getResource(fxmlResource));
Scene scene = new Scene(page);
newStage.setScene(scene);
newStage.setTitle(windowTitle);
newStage.setResizable(isResizable);
if(showRightAway)
{
newStage.show();
}
}
newStage
serait la nouvelle fenêtre. Le problème est que je ne trouve pas de moyen de dire au contrôleur où chercher les informations du client (en passant l'id comme paramètre).
Des idées?
Réponses:
Approche recommandée
Cette réponse énumère différents mécanismes pour transmettre des paramètres aux contrôleurs FXML.
Pour les petites applications, je recommande fortement de passer des paramètres directement de l'appelant au contrôleur - c'est simple, direct et ne nécessite aucun cadre supplémentaire.
Pour les applications plus grandes et plus complexes, il serait utile de rechercher si vous souhaitez utiliser les mécanismes d' injection de dépendance ou de bus d'événements dans votre application.
Passage direct des paramètres de l'appelant au contrôleur
Passez des données personnalisées à un contrôleur FXML en récupérant le contrôleur à partir de l'instance de chargeur FXML et en appelant une méthode sur le contrôleur pour l'initialiser avec les valeurs de données requises.
Quelque chose comme le code suivant:
Un nouveau FXMLLoader est construit comme indiqué dans l'exemple de code ie
new FXMLLoader(location)
. L'emplacement est une URL et vous pouvez générer une telle URL à partir d'une ressource FXML en:Faites attention de NE PAS utiliser de fonction de chargement statique sur le FXMLLoader, sinon vous ne pourrez pas obtenir votre contrôleur à partir de votre instance de chargeur.
Les instances FXMLLoader elles-mêmes ne savent jamais rien des objets de domaine. Vous ne passez pas directement des objets de domaine spécifiques à l'application dans le constructeur FXMLLoader, mais vous:
Ce blog (par un autre auteur) fournit un autre, mais similaire, par exemple .
Configuration d'un contrôleur sur FXMLLoader
Vous pouvez construire un nouveau contrôleur dans le code, en transmettant tous les paramètres de votre appelant au constructeur du contrôleur. Une fois que vous avez construit un contrôleur, vous pouvez le définir sur une instance FXMLLoader avant d'appeler la méthode d'
load()
instance .Pour définir un contrôleur sur un chargeur (dans JavaFX 2.x), vous NE POUVEZ PAS également définir un
fx:controller
attribut dans votre fichier fxml.En raison de la limitation de la
fx:controller
définition dans FXML, je préfère personnellement obtenir le contrôleur du FXMLLoader plutôt que de le configurer dans le FXMLLoader.Demander au contrôleur d'extraire les paramètres d'une méthode statique externe
Cette méthode est illustrée par la réponse de Sergey à Javafx 2.0 How-to Application.getParameters () dans un fichier Controller.java .
Utiliser l'injection de dépendance
FXMLLoader prend en charge les systèmes d'injection de dépendances comme Guice, Spring ou Java EE CDI en vous permettant de définir une fabrique de contrôleurs personnalisée sur FXMLLoader. Cela fournit un rappel que vous pouvez utiliser pour créer l'instance de contrôleur avec des valeurs dépendantes injectées par le système d'injection de dépendance respectif.
Un exemple d'injection JavaFX d'application et de dépendance de contrôleur avec Spring est fourni dans la réponse à:
Une approche d'injection de dépendances vraiment agréable et propre est illustrée par le framework afterburner.fx avec un exemple d'application air-hacks qui l'utilise. afterburner.fx s'appuie sur JEE6 javax.inject pour effectuer l'injection de dépendance.
Utiliser un bus d'événements
Greg Brown, le créateur et implémenteur d'origine de la spécification FXML, suggère souvent d'envisager l'utilisation d'un bus d'événements, tel que le Guava EventBus , pour la communication entre les contrôleurs instanciés FXML et d'autres logiques d'application.
Questions et réponses sur le suivi
Il s'agit d'une solution fonctionnelle à un problème. Une étape est renvoyée par la
showCustomerDialog
fonction afin qu'une référence à celle-ci puisse être stockée par une classe externe qui souhaitera peut-être faire quelque chose, comme masquer l'étape en fonction d'un clic sur le bouton dans la fenêtre principale, ultérieurement. Une autre solution orientée objet pourrait encapsuler la fonctionnalité et la référence d'étape à l'intérieur d'un objet CustomerDialog ou avoir une étape d'extension CustomerDialog. Un exemple complet d'interface orientée objet vers une boîte de dialogue personnalisée encapsulant des données FXML, de contrôleur et de modèle dépasse le cadre de cette réponse, mais peut constituer un article de blog intéressant pour quiconque est enclin à en créer un.Informations supplémentaires fournies par l'utilisateur StackOverflow nommé @dzim
Exemple pour l'injection de dépendance de démarrage de Spring
La question de savoir comment le faire "The Spring Boot Way", il y avait une discussion sur JavaFX 2, que j'ai répondu dans le permalien ci-joint. L'approche est toujours valide et testée en mars 2016, sur Spring Boot v1.3.3.RELEASE: https://stackoverflow.com/a/36310391/1281217
Parfois, vous souhaiterez peut-être transmettre les résultats à l'appelant, auquel cas vous pouvez consulter la réponse à la question connexe:
la source
Dans cet exemple, nous utiliserons 5 fichiers:
Tous les fichiers sont répertoriés dans leur intégralité au bas de cet article.
L'objectif: Pour démontrer les valeurs de passage
Controller1
àController2
et vice - versa.Le déroulement du programme:
TextField
, aButton
et aLabel
. Lorsque vousButton
cliquez sur, la deuxième fenêtre est chargée et affichée, y compris le texte entré dans leTextField
.TextField
, unButton
et unLabel
. LeLabel
affiche le texte saisi dans leTextField
la première scène.TextField
et en cliquant sur sonButton
, la première scèneLabel
est mise à jour pour afficher le texte saisi.Il s'agit d'une démonstration très simple et pourrait certainement représenter une certaine amélioration, mais devrait rendre le concept très clair.
Le code lui-même est également commenté avec quelques détails sur ce qui se passe et comment.
Main.java:
Controller1.java:
Controller2.java:
Layout1.fxml:
Layout2.fxml:
la source
loader.setController(this)
et l'ajout du contrôleur dans le fichier FXML plante l'applicationloader.getController()
La classe javafx.scene.Node a une paire de méthodes setUserData (Object) et Object getUserData ()
Que vous pourriez utiliser pour ajouter vos informations au nœud.
Vous pouvez donc appeler page.setUserData (info);
Et le contrôleur peut vérifier si les informations sont définies. En outre, vous pouvez utiliser ObjectProperty pour le transfert de données en amont, si nécessaire.
Observez une documentation ici: http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html Avant la phrase "Dans la première version, le handleButtonAction () est marqué avec @FXML pour autoriser le balisage défini dans le document du contrôleur à l'invoquer. Dans le deuxième exemple, le champ du bouton est annoté pour permettre au chargeur de définir sa valeur. La méthode initialize () est également annotée. "
Vous devez donc associer un contrôleur à un nœud et définir des données utilisateur sur le nœud.
la source
Voici un exemple pour passer des paramètres à un document fxml via un espace de noms.
Définissez la valeur
External Text
de la variable d'espace de nomslabelText
:la source
FXMLLoader.CONTROLLER_KEYWORD
,FXMLLoader.LOCATION_KEY
,FXMLLoader.RESOURCES_KEY
et toute chaîne utilisée comme valeur de l'fx:id
attribut.Cela marche ..
Rappelez-vous que la première fois que vous imprimez la valeur de passage, vous obtiendrez null, vous pouvez l'utiliser après le chargement de vos fenêtres, de même pour tout ce que vous voulez coder pour tout autre composant.
la source
Vous devez créer une classe de contexte.
Vous devez simplement définir l'instance du contrôleur lors de l'initialisation en utilisant
et vous pouvez l'utiliser à partir de votre application entière en utilisant simplement
Vous pouvez maintenant transmettre des paramètres à n'importe quel contrôleur à partir de l'application entière.
la source
Oui, vous pouvez.
Vous devez ajouter le premier contrôleur:
Puis dans le second déclarez un client, puis en bas de votre contrôleur:
la source
Voici un exemple d'utilisation d'un contrôleur injecté par Guice.
Voici une implémentation concrète du chargeur:
Notez que cet exemple charge la vue au centre d'un BoarderPane qui est la racine de la scène dans la scène. Ceci n'est pas pertinent pour l'exemple (détail d'implémentation de mon cas d'utilisation spécifique) mais a décidé de le laisser car certains pourraient le trouver utile.
la source
Vous pouvez décider d'utiliser une liste publique observable pour stocker des données publiques, ou simplement créer une méthode de définition publique pour stocker les données et les récupérer à partir du contrôleur correspondant
la source
Pourquoi répondre à une question de 6 ans?
L'un des concepts les plus fondamentaux de tout langage de programmation est de savoir comment naviguer d'un (fenêtre, formulaire ou page) à un autre. De plus, lors de cette navigation, le développeur souhaite souvent transmettre des données à partir d'une (fenêtre, formulaire ou page) et afficher ou utiliser les données transmises.Bien
que la plupart des réponses ici fournissent des exemples bons à excellents comment accomplir cela, nous pensions que nous allions le faire un cran ou deux ou trois
Nous avons dit trois parce que nous naviguerons entre trois (fenêtre, formulaire ou page) et utiliserons le concept de variables statiques pour transmettre des données autour de (fenêtre, formulaire ou page)
Nous inclurons également un code de prise de décision tout en nous naviguons
Démarrer le contrôleur
Page One Controller
Page deux contrôleur
Voici tous les fichiers FXML
la source