Wie kann ich Parameter an ein sekundäres Fenster in javafx übergeben? Gibt es eine Möglichkeit, mit dem entsprechenden Controller zu kommunizieren?
Beispiel: Der Benutzer wählt einen Kunden aus a aus TableView
und ein neues Fenster mit den Kundeninformationen wird geöffnet.
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
wäre das neue Fenster. Das Problem ist, dass ich keine Möglichkeit finde, dem Controller mitzuteilen, wo nach Kundeninformationen gesucht werden soll (indem die ID als Parameter übergeben wird).
Irgendwelche Ideen?
Antworten:
Empfohlener Ansatz
Diese Antwort listet verschiedene Mechanismen zum Übergeben von Parametern an FXML-Controller auf.
Für kleine Anwendungen empfehle ich dringend, Parameter direkt vom Aufrufer an die Steuerung zu übergeben - es ist einfach, unkompliziert und erfordert keine zusätzlichen Frameworks.
Für größere, kompliziertere Anwendungen lohnt es sich zu untersuchen, ob Sie in Ihrer Anwendung Abhängigkeitsinjektions- oder Ereignisbusmechanismen verwenden möchten .
Parameter direkt vom Anrufer an den Controller übergeben
Übergeben Sie benutzerdefinierte Daten an einen FXML-Controller, indem Sie den Controller aus der FXML-Loader-Instanz abrufen und eine Methode auf dem Controller aufrufen, um ihn mit den erforderlichen Datenwerten zu initialisieren.
So etwas wie der folgende Code:
Ein neuer FXMLLoader wird wie im Beispielcode gezeigt erstellt, d
new FXMLLoader(location)
. H. Der Speicherort ist eine URL, und Sie können eine solche URL aus einer FXML-Ressource generieren, indem Sie:Achten Sie darauf, KEINE statische Ladefunktion für den FXMLLoader zu verwenden, da Sie sonst Ihren Controller nicht von Ihrer Loader-Instanz abrufen können.
FXMLLoader-Instanzen selbst wissen nie etwas über Domänenobjekte. Sie übergeben anwendungsspezifische Domänenobjekte nicht direkt an den FXMLLoader-Konstruktor, sondern:
Dieser Blog (von einem anderen Autor) bietet ein alternatives, aber ähnliches Beispiel .
Festlegen eines Controllers im FXMLLoader
Sie können einen neuen Controller im Code erstellen und alle gewünschten Parameter von Ihrem Aufrufer an den Controller-Konstruktor übergeben. Nachdem Sie einen Controller erstellt haben, können Sie ihn für eine FXMLLoader-Instanz festlegen, bevor Sie die
load()
Instanzmethode aufrufen .Um einen Controller auf einem Loader (in JavaFX 2.x) festzulegen, können Sie NICHT auch ein
fx:controller
Attribut in Ihrer fxml-Datei definieren.Aufgrund der Einschränkung der
fx:controller
Definition in FXML ziehe ich es persönlich vor, den Controller vom FXMLLoader zu beziehen, anstatt den Controller in den FXMLLoader zu setzen.Lassen Sie den Controller Parameter von einer externen statischen Methode abrufen
Diese Methode wird durch die Antwort von Sergey auf Javafx 2.0 How-to Application.getParameters () in einer Controller.java-Datei veranschaulicht .
Verwenden Sie die Abhängigkeitsinjektion
FXMLLoader unterstützt Abhängigkeitsinjektionssysteme wie Guice, Spring oder Java EE CDI, indem Sie eine benutzerdefinierte Controller-Factory auf dem FXMLLoader festlegen können. Dies bietet einen Rückruf, mit dem Sie die Controller-Instanz mit abhängigen Werten erstellen können, die vom jeweiligen Abhängigkeitsinjektionssystem eingespeist werden.
Ein Beispiel für die Injektion von JavaFX-Anwendungen und Controller-Abhängigkeiten mit Spring finden Sie in der Antwort auf:
Ein wirklich netter, sauberer Ansatz zur Abhängigkeitsinjektion wird durch das afterburner.fx-Framework mit einer Beispielanwendung für Air-Hacks veranschaulicht , die es verwendet. afterburner.fx verwendet JEE6 javax.inject , um die Abhängigkeitsinjektion durchzuführen.
Verwenden Sie einen Ereignisbus
Greg Brown, der ursprüngliche Ersteller und Implementierer von FXML-Spezifikationen, schlägt häufig vor, die Verwendung eines Ereignisbusses wie des Guava EventBus für die Kommunikation zwischen FXML-instanziierten Controllern und anderer Anwendungslogik in Betracht zu ziehen .
Follow-up-Fragen und Antworten
Es ist eine funktionale Lösung für ein Problem. Eine Stufe wird von der
showCustomerDialog
Funktion zurückgegeben, damit ein Verweis darauf von einer externen Klasse gespeichert werden kann, die möglicherweise etwas tun möchte, z. B. die Stufe zu einem späteren Zeitpunkt durch Klicken auf eine Schaltfläche im Hauptfenster ausblenden. Eine alternative, objektorientierte Lösung könnte die Funktionalität und die Bühnenreferenz in einem CustomerDialog-Objekt kapseln oder eine CustomerDialog-Erweiterungsstufe haben. Ein vollständiges Beispiel für eine objektorientierte Schnittstelle zu einem benutzerdefinierten Dialogfeld, das FXML-, Controller- und Modelldaten enthält, würde den Rahmen dieser Antwort sprengen, kann jedoch für jeden, der dazu neigt, einen zu erstellen, einen lohnenden Blog-Beitrag darstellen.Zusätzliche Informationen vom StackOverflow-Benutzer @dzim
Beispiel für Spring Boot Dependency Injection
Bei der Frage, wie es geht "The Spring Boot Way", gab es eine Diskussion über JavaFX 2, die ich im angehängten Permalink beantwortet habe. Der Ansatz ist noch gültig und wurde im März 2016 auf Spring Boot v1.3.3.RELEASE getestet: https://stackoverflow.com/a/36310391/1281217
Manchmal möchten Sie die Ergebnisse möglicherweise an den Anrufer zurückgeben. In diesem Fall können Sie die Antwort auf die entsprechende Frage überprüfen:
quelle
In diesem Beispiel werden 5 Dateien verwendet:
Alle Dateien werden in ihrer Gesamtheit am Ende dieses Beitrags aufgelistet.
Das Ziel: Übergeben von Werten von
Controller1
nachController2
und umgekehrt.Der Programmablauf:
TextField
, aButton
und aLabel
. Wenn Sie aufButton
klicken, wird das zweite Fenster geladen und angezeigt, einschließlich des in das Feld eingegebenen TextsTextField
.TextField
, aButton
und aLabel
. DasLabel
zeigt den Text an, derTextField
in der ersten Szene eingegeben wurde .TextField
und darauf klickenButton
, wird die erste SzeneLabel
aktualisiert, um den eingegebenen Text anzuzeigen.Dies ist eine sehr einfache Demonstration und könnte sicherlich für eine Verbesserung stehen, sollte aber das Konzept sehr klar machen.
Der Code selbst wird auch mit einigen Details darüber kommentiert, was wie passiert.
Main.java:
Controller1.java:
Controller2.java:
Layout1.fxml:
Layout2.fxml:
quelle
loader.setController(this)
und das Hinzufügen des Controllers in der FXML-Datei stürzt die Anwendung abloader.getController()
Die Klasse javafx.scene.Node verfügt über zwei Methoden: setUserData (Object) und Object getUserData ()
Mit denen Sie Ihre Daten zum Knoten hinzufügen können.
Sie können also page.setUserData (info) aufrufen.
Und der Controller kann prüfen, ob Informationen eingestellt sind. Bei Bedarf können Sie ObjectProperty auch für die Rückwärtsübertragung von Daten verwenden.
Beachten Sie hier eine Dokumentation: http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html Vor dem Satz "In der ersten Version ist handleButtonAction () mit @FXML gekennzeichnet Damit das im Dokument des Controllers definierte Markup es aufrufen kann. Im zweiten Beispiel wird das Schaltflächenfeld mit Anmerkungen versehen, damit der Loader seinen Wert festlegen kann. Die Methode initialize () ist ebenfalls mit Anmerkungen versehen. "
Sie müssen also einen Controller einem Knoten zuordnen und Benutzerdaten für den Knoten festlegen.
quelle
Hier ist ein Beispiel für die Übergabe von Parametern an ein fxml-Dokument über den Namespace.
Wert
External Text
für Namespace-Variable definierenlabelText
:quelle
FXMLLoader.CONTROLLER_KEYWORD
,FXMLLoader.LOCATION_KEY
,FXMLLoader.RESOURCES_KEY
und eine beliebige Zeichenfolge als Wert für das verwendetefx:id
Attribut.Das funktioniert ..
Denken Sie daran, dass Sie beim ersten Drucken des übergebenen Werts null erhalten. Sie können ihn nach dem Laden Ihrer Fenster verwenden. Dies gilt auch für alles, was Sie für eine andere Komponente codieren möchten.
quelle
Sie müssen eine Kontextklasse erstellen.
Sie müssen nur die Instanz des Controllers bei der Initialisierung mit festlegen
und Sie können es aus Ihrer gesamten Anwendung nur mit verwenden
Jetzt können Sie Parameter aus der gesamten Anwendung an jeden Controller übergeben.
quelle
Ja, du kannst.
Sie müssen im ersten Controller hinzufügen:
Dann deklarieren Sie im zweiten einen Client und dann am unteren Rand Ihres Controllers:
quelle
Hier ist ein Beispiel für die Verwendung eines von Guice injizierten Controllers.
Hier ist eine konkrete Implementierung des Laders:
Beachten Sie, dass in diesem Beispiel die Ansicht in die Mitte eines BoarderPane geladen wird, das die Wurzel der Szene in der Bühne darstellt. Dies ist für das Beispiel irrelevant (Implementierungsdetail meines spezifischen Anwendungsfalls), hat jedoch beschlossen, es beizubehalten, da einige es möglicherweise nützlich finden.
quelle
Sie können eine öffentlich beobachtbare Liste zum Speichern öffentlicher Daten verwenden oder einfach eine öffentliche Setter-Methode erstellen, um Daten zu speichern und vom entsprechenden Controller abzurufen
quelle
Warum eine 6 Jahre alte Frage beantworten?
Eines der grundlegendsten Konzepte für jede Programmiersprache ist die Navigation von einem (Fenster, Formular oder Seite) zum anderen. Auch während dieser Navigation möchte der Entwickler häufig Daten von einem (Fenster, Formular oder Seite) übergeben und die übergebenen Daten anzeigen oder verwenden.
Während die meisten Antworten hier gute bis hervorragende Beispiele dafür liefern, dachten wir, wir würden sie auf den Kopf stellen eine Kerbe oder zwei oder drei
Wir sagten drei, weil wir zwischen drei (Fenster, Formular oder Seite) navigieren und das Konzept der statischen Variablen verwenden, um Daten um das Fenster (Formular, Formular oder Seite)
herumzuleiten wir navigieren
Starten Sie den Controller
Page One Controller
Seite Zwei Controller
Unten finden Sie alle FXML-Dateien
quelle