Elemente auf vorheriger Stage, nach Wechsel der Stage ansprechen

Tintenfisch

Bekanntes Mitglied
Hallo allerseits,
Zur Lege: Ich greife aus ControllerClassA auf eine Methode in einer ControllerClassB zu, welche ein Pop-Up Öffnet. Mit dem Pup-Up kann durch einen Button wieder auf eine Methode in der ControllerClassA zugegriffen werden. Dies Funktioniert auch alles reibungslos, jedoch musste ich feststellen, dass nun zurück in der ControllerClassA, keine Elemente in dieser Klasse, wie Textfelder mehr geändert werden können. Quasi als wäre die "Sitzung", nach dem Öffnen einer neuen Stage (dem Pop-Up), dort abgelaufen.
Würde mich freuen, wenn jemand eine Idee hätte, wie man die Elemente wieder wie gewohnt ändern kann.
 
meinst du dass das haupt fenster nicht "benutztbar" ist solange b offen ist ? das wäre die window modality .. das ist das bekannte wenn ein pop up aufkommt und du in den hintergrund klickst und dann der windows fehler sound kommt, dh das hauptfesnter ist immun gegen user input aber nicht von code änderungen

zb du änderst durch code den text dann kann der text im hauptfenster geändert werden, aber nicht durch eingabe von maus oder tastatur

( das alles gilt wenn du javafx hernimmst )
 
meinst du dass das haupt fenster nicht "benutztbar" ist solange b offen ist ? das wäre die window modality .. das ist das bekannte wenn ein pop up aufkommt und du in den hintergrund klickst und dann der windows fehler sound kommt, dh das hauptfesnter ist immun gegen user input aber nicht von code änderungen

zb du änderst durch code den text dann kann der text im hauptfenster geändert werden, aber nicht durch eingabe von maus oder tastatur

( das alles gilt wenn du javafx hernimmst )
Vorab vielen dank für die Antwort.
Klicken tue ich nur im Pop-Up, jedoch wird durch den Klick auf eine Methode in der Klasse vor dem Pop-Up zugegriffen. Die Logik in der Methode funktioniert auch, nur soll zuletzt noch der Inhalt der Felder (nicht im Pop-Up, sondern in der vorherigen Stage) entfernt werden mit textfield.clear();.
Da dies bisher ohne Pop-Up keinerlei Probleme dargestellt hat, stehe ich dabei bisschen auf dem Schlauch.

Zudem scheint es unabhängig davon zu sein, ob das Pop-Up beim Methodenzugriff bereits geschlossen ist oder nicht, da beides das selbe Ergebnis zeigt.
 
vllt zeigst du mal code und erklärst anhand vom code woran du denkst dass es nicht passt.. das texfeld.clear muss funktionieren das kann nicht nicht funtkionieren
 
vllt zeigst du mal code und erklärst anhand vom code woran du denkst dass es nicht passt.. das texfeld.clear muss funktionieren das kann nicht nicht funtkionieren
bis auf das clear(); funktioniert alles in der Methode und die fx:id ist in der FXML ist auch okay.

Java:
public class ControllerClassA {
   
    @FXML private TextField isinTFInput;
   
    public void deleteOrderItem () throws SQLException, IOException {
        String isin = tempItemDelete;
        String tableType = tempTableDelete;
               
        DBStatement dbStatement = new DBStatement();
       
        if (tableType == "Buy") {
            dbStatement.deleteItemFromDB("buyData", "isin", isin);
        } else if (tableType == "Sell") {
            dbStatement.deleteItemFromDB("sellData", "isin", isin);
        } else if (tableType == "") {

        }
       
        isinTFInput.clear();
    }
}
 
kannst du ein system out println for das clear setzen ob du überhaupt da hin kommst

und wer ruft die methode auf und wie ?
 
Woher kommt denn der Wert in tempTableDelete? Du macht String Vergleiche mit == was nur funktioniert, wenn die Strings die gleiche Referenz haben und die sind nur gleich, wenn diese per String.intern() auf einer String-Liste des Systems stehen (was nur der Fall ist für Literale und so).

Die Chance ist also groß, dass es einfach nur an den Vergleichen liegt, dass Deine Methode deleteOrderItem nichts macht, da einfach keine Bedingung wahr ist.

Ein Vergleich wie: (tableType == "Buy") sollte also etwas sein wie:
("Buy".equals(tableType))
oder
(Objects.equals(tableType, "Buy"))
oder wenn sicher ist, dass tableType nicht null sein kann:
(tableType.equals("Buy"))

Und das Gleiche gilt halt für alle Bedingungen, die Du abprüfen willst.

Alternativ kann man hier natürlich auch mit einem Switch Statement arbeiten.
 
kannst du ein system out println for das clear setzen ob du überhaupt da hin kommst

und wer ruft die methode auf und wie ?
Bis dahin kommt es, der Code zuvor wird auch ausgeführt.
Aufrufen tut die Methode das Pop-Up mit einer separaten Klasse. Das Funktionier auch alles soweit.

Ich habe eben das TextField an sich in ein Sys.out gesetzt, es wird an sich auch erkannt, zeigt die korrekte id und so.
Java:
public class ControllerClassB {
    
    public void confirmOderOptionDelition (ActionEvent event) throws IOException, SQLException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlString));
        root = loader.load();
        if (fxmlString.equals("Options.fxml")) {
            FXMLOptionsController optionsController = loader.getController();
            optionsController.getListViewItemAndDelete();
        } else if (fxmlString.equals("Input.fxml")) {
            FXMLInputController inputController = loader.getController();
            inputController.deleteOrderItem();
            
        }
        stage = (Stage)((Node)event.getSource()).getScene().getWindow();
        stage.close();
    }
}
 
Woher kommt denn der Wert in tempTableDelete? Du macht String Vergleiche mit == was nur funktioniert, wenn die Strings die gleiche Referenz haben und die sind nur gleich, wenn diese per String.intern() auf einer String-Liste des Systems stehen (was nur der Fall ist für Literale und so).

Die Chance ist also groß, dass es einfach nur an den Vergleichen liegt, dass Deine Methode deleteOrderItem nichts macht, da einfach keine Bedingung wahr ist.

Ein Vergleich wie: (tableType == "Buy") sollte also etwas sein wie:
("Buy".equals(tableType))
oder
(Objects.equals(tableType, "Buy"))
oder wenn sicher ist, dass tableType nicht null sein kann:
(tableType.equals("Buy"))

Und das Gleiche gilt halt für alle Bedingungen, die Du abprüfen willst.

Alternativ kann man hier natürlich auch mit einem Switch Statement arbeiten.
tempDeleteItem kommt ursprünglich aus dem TextField isinTFInput und wird in einer vorherigen Methode zwischengespeichert. Gut zu wissen, danke, dann sollte ich mir das mit dem equals echt mal angewöhnen.
An sich funktioniert der Code in der Methode allerdings. Es hängt irgendwie nur am isinTFInput.clear();
 
isinTFInput.setText("");
du kannst das probieren da .clear() versucht das caret und den fokus zu korrigieren aber dein window kann keinen fokus haben vllt hängts daran
Java:
    /**
     * Clears the text.
     */
    public void clear() {
        deselect();
        if (!text.isBound()) {
            setText("");
        }
    }
... oracle docs vom feinsten ( ich gehe davon aus dass das wirklich dein ganzer code ist und kein ausgeschnipsle )
 
tempDeleteItem kommt ursprünglich aus dem TextField
Dann sollte es eigentlich nie funktionieren, denn die Strings aus dem TextField sollten nie Referenzgleich zu irgendwelchen Literalen sein.

Ein einfacher schneller Test nur für Dich:
Java:
package application;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.event.ActionEvent;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    private TextField textField;
    @Override
    public void start(Stage primaryStage) {

        Pane pane = new Pane();
        textField = new TextField();
        pane.getChildren().add(textField);
        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.show();

        textField.textProperty().addListener(this::textFieldAction);
    }

    private void textFieldAction(Observable observable) {
        String text = textField.getText();
        if (text == "Hallo") {
            System.out.println("Hallo gefunden!");
        } else {
            System.out.println("'" + text + "' is not 'Hallo'");
        }
    }

}

Und siehe da - wenn Du da Hallo eingibst, bekommst Du die Ausgabe:
Code:
'H' is not 'Hallo'
'Ha' is not 'Hallo'
'Hal' is not 'Hallo'
'Hall' is not 'Hallo'
'Hallo' is not 'Hallo'
 
du kannst das probieren da .clear() versucht das caret und den fokus zu korrigieren aber dein window kann keinen fokus haben vllt hängts daran
Java:
    /**
     * Clears the text.
     */
cs vom feinsten ( ich gehe davon aus dass das wirklich dein ganzer code ist und kein ausgeschnipsle )
[/QUOTE]
leider auch ohne Erfolg. Wenn ich get.text(); in einem System.out. versuche, wird ebenso nichts ausgegeben.
 
kann es sein dass du einen zweiten controller erstellt hast und nicht den echten referenzierst sondern den zweiten
 
Aber dann weiß ich schonmal, dass das an sich kein Problem sein dürfte und es einfach nur an dem Fehler meinerseits liegt. Dann mach ich mich mal nach und nach auf die Suche danach.

Vielen dank beiderseits 🙂

Ich muss tatsächlich nochmal auf das Thema zurückkommen, denn leider hat sich noch keinerlei Lösung gefunden. Allerdings ist es nun an anderer Stelle zu dem gleichen Problem gekommen. Diesmal ist es eine TableView, welche nicht auf Änderungen reagiert.
Allgemein lässt sich sagen, dass wenn eine onAction Methode in einer anderen Klasse, als die, die für die angezeigte Oberfläche zuständig ist, aufgerufen wird, die Oberfläche keine Veränderungen anzeigt. Egal ob Text Änderungen im Textfeld, auf Buttons oder Tables, Änderungen werden nicht angezeigt, jedoch auch kein Fehler gemeldet.
Leider erklärt sich dies für mich ganz und gar nicht, daher bitte ich nochmals um eure Unterstützung.
 
dann poste deinen code und mach kein rate spiel draus
onAction funktioniert soweit und die Methode im Controller wird auch erreicht. Das Problem stellt sich ähnlich dar, wie das zuerst gezeigte in diesem Thema, mit fehlender Reaktion der GUI.

Java:
// Klasse für Daten der TableView
public class Order {
    private int id;

    public Order (int id) {
        this.idEx = id;
 
        this.editBtEx = new Button("Edit");
        this.deleteBtEx = new Button("Delete");
        this.optionHBEx = new HBox(this.editBtEx, this.deleteBtEx);
     
        this.deleteBtEx.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                DBStatement dbStatement = new DBStatement();
                try {
                    dbStatement.deleteItemFromDB("id", id);
                    try {
                        FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
                        Parent root = loader.load();
                        FXMLViewController controller = loader.getController();
                        controller.existingAssetsTab.setText("test");
                        controller.removeItemFromTableView (int tableViewIndex);

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}


Java:
    // In Controller Class der betroffenen Scene
    public void  removeItemFromTableView (int tableViewIndex) {

        exTableView.getItems().clear();
        setDataExistingAssetsTableView();
        exTableView.refresh();
        existingAssetsTab.setText("test"); // nur als Test, funktioniert nicht, genau wie getText, zeigt jedoch keinerlei Fehler
        System.out.println("Test"); // funktioniert
    }
public void setDataBuyTableView () {
        DBStatement dbStatement = new DBStatement();
        try {
            buyTableView.setItems(dbStatement.getBuyOrders());
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
 
Zuletzt bearbeitet:
Theoretisch erscheint es mir so, als würde auf die Attribute einer anderen Instanz zugegriffen werden, da der Zugriff auf die jeweiligen Methoden reibungslos funktioniert, jedoch die Attribute zwar angesprochen werden können, also keinen Fehler zeigen, aber in der GUI nicht reagieren.
Vom Code her dürfte das zwar meines Erachtens zwar nicht sein, aber war so ein Gedanke.
 
die GUI kann nicht nicht reagieren... ich denke mal wie auch oben schon erwähnt setzt du 1e gui auf den bildschirm und mit der tust du nix, und eine GUI hast du nur als objekt ohne szene graph am laufen dh du setzt vom falschen die werte.. du wirst 2 objekte haben

existingAssetsTab.setText("test"); // nur als Test, funktioniert nicht, genau wie getText, zeigt jedoch keinerlei Fehler

könntest du vllt das ganze teil wo hochladen oder ein teilbares paket geben ? ( zb in git )

EDIT: möchte nurmal auf #13 verweisen.. .hust hust..

Java:
                        FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
                        Parent root = loader.load();
                        FXMLViewController controller = loader.getController();
                        controller.existingAssetsTab.setText("test");
                        controller.removeItemFromTableView (int tableViewIndex);
zb hier setzt du root niemals in den szene graphen ein vllt im controller dass er sich selber einsetzt aber das bezweifle ich gerade mal weil du sonst nicht root geholt hättest

und da es hier passiert ist denke ich mal dass es auch woanders passiert sein könnte
 
Zuletzt bearbeitet von einem Moderator:
die GUI kann nicht nicht reagieren... ich denke mal wie auch oben schon erwähnt setzt du 1e gui auf den bildschirm und mit der tust du nix, und eine GUI hast du nur als objekt ohne szene graph am laufen dh du setzt vom falschen die werte.. du wirst 2 objekte haben



könntest du vllt das ganze teil wo hochladen oder ein teilbares paket geben ? ( zb in git )

EDIT: möchte nurmal auf #13 verweisen.. .hust hust..

Java:
                        FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
                        Parent root = loader.load();
                        FXMLViewController controller = loader.getController();
                        controller.existingAssetsTab.setText("test");
                        controller.removeItemFromTableView (int tableViewIndex);
zb hier setzt du root niemals in den szene graphen ein vllt im controller dass er sich selber einsetzt aber das bezweifle ich gerade mal weil du sonst nicht root geholt hättest

und da es hier passiert ist denke ich mal dass es auch woanders passiert sein könnte
Inwieweit root in den Scene Graphen setzen, tatsächlich habe ich das überall so. Später hatte ich das "Parent root" weggelassen, da es mit "loader.load(); genau so funktionierte (oder eben auch nicht). Die Scene kommt bei mir an sich nur dann, wenn ich eine neue erstellen muss, für eine andere Seite.
Java:
FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
loader.load();
FXMLViewController controller = loader.getController();
controller.existingAssetsTab.setText("test");
 
mich wundert es gerade dass du irgendwas auf den bildschirm hast

1. du musst eine scene haben die ein root element hat was auch immer das ist
2. wenn du ein FXML lädst musst du das auch einklinken in die szene/node baum um das auch sehen zu können

das ist was du tust
FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
du richtest dir einen großen eimer her um sachen rein zu tun
du sammelst dir paar buttons und tust sie dir in deinen eimer
FXMLViewController controller = loader.getController();
holst dir den könig der sachen die du in den eimer gepackt hast
controller.existingAssetsTab.setText("test");
sagst dem könig dass er den text von seinen leuten ändern soll

und dann wirfst du den eimer mit einer beeindruckenden geschwindigkeit vom fenster raus weil du ihn niemals speicherst.. und das fenster wäre in java der garbage collector der alles aufsammelt was du nicht mehr benutzen kannst

Java:
                        FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
                        Parent root = loader.load();
                        FXMLViewController controller = loader.getController();
                        controller.existingAssetsTab.setText("test");
                        controller.removeItemFromTableView (int tableViewIndex);
alle diese objekte sind nach dem durchlauf nicht mehr benutzbar weil du sie in eine geschweifte klammer geschrieben hast und nirgendswo außerhalb gespeichert oder referenziert hast ( was ansich das gleiche ist )
 
mich wundert es gerade dass du irgendwas auf den bildschirm hast

1. du musst eine scene haben die ein root element hat was auch immer das ist
2. wenn du ein FXML lädst musst du das auch einklinken in die szene/node baum um das auch sehen zu können

das ist was du tust

du richtest dir einen großen eimer her um sachen rein zu tun

du sammelst dir paar buttons und tust sie dir in deinen eimer

holst dir den könig der sachen die du in den eimer gepackt hast

sagst dem könig dass er den text von seinen leuten ändern soll

und dann wirfst du den eimer mit einer beeindruckenden geschwindigkeit vom fenster raus weil du ihn niemals speicherst.. und das fenster wäre in java der garbage collector der alles aufsammelt was du nicht mehr benutzen kannst

Java:
                        FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
                        Parent root = loader.load();
                        FXMLViewController controller = loader.getController();
                        controller.existingAssetsTab.setText("test");
                        controller.removeItemFromTableView (int tableViewIndex);
alle diese objekte sind nach dem durchlauf nicht mehr benutzbar weil du sie in eine geschweifte klammer geschrieben hast und nirgendswo außerhalb gespeichert oder referenziert hast ( was ansich das gleiche ist )
Bei jedem Wechsel der Scene erstelle ich eine neue Scene.
Java:
@FXML
private void toViewScene (ActionEvent event) throws IOException {
    root = FXMLLoader.load(getClass().getResource("View.fxml"));
    stage = (Stage)((Node)event.getSource()).getScene().getWindow();
    scene = new Scene(root, 800, 600);
    stage.setScene(scene);
    stage.show();
}

Die werden so quasi in jedem Controller für die jeweiligen Scenen erstellt.
Wie setze ich die Scene denn, ich habe mal mit dem probiert, was ich so dachte, aber leider ohne Erfolg, da die Scene als null gezeigt wird.

Java:
FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
Parent root = loader.load();
FXMLViewController controller = loader.getController();                   
Scene scene = controller.viewBorderPane.getScene();
scene.setRoot(root);
controller.existingAssetsTab.setText("test");
 
@Tintenfisch, sorry, wenn ich mich kurz einmische, aber dieses Rumgerate führt doch zu nichts.

In #17 zeigst Du Code, der eine View lädt (wobei ein Controller erzeugt wird) und im Controller irgendwelche Einstellungen vornimmt. Die View wird nirgends verwendet. In #22 erklärst Du, dass Du den Szenenwechsel anders vornimmst: Du lädst (vermutlich) wieder eine View. Insofern hast Du zwei Views und zwei Controller, was @yfons123 in #13 und #19 bereits angesprochen hat. Aber anhand von ein paar Schnipseln ist es kaum möglich, definitive Aussagen zu treffen.

Bau doch mal eine kleine JavaFX-Anwendung zusammen, die das Problem zeigt, damit man dieses auch wirklich nachvollziehen kann.
 
Ich persönlich halte es für unschön, wenn sich unterschiedliche Controller gegenseitig kennen müssen. Um Abhängigkeiten zu vermeiden, verwende ich gerne Messaging, d.h. Jeder, der am Messaging teilnehmen soll, erhält (per Konstruktorinjektion) eine Instanz auf einen "MessageBus" und kann sich für den Empfang von bestimmten Nachrichten registrieren oder selbst Nachrichten an andere senden. In den jeweiligen Controllern müssen demnach Handlermethoden für die unterschiedlichen Nachrichten implementiert werden.
Ich hab "meinen" MessageBus selbst geschrieben. Es gibt auch fertige Lösungen, z. B. Guava
 
Ich habe mal eine Beispielanwendung geschrieben, in welcher das Problem deutlich wird.
Das Öffnen der neuen Stage funktioniert., sowie auch der Zugriff auf die Methoden des jeweils anderen Controllers. Lediglich die Veränderung von z.B. dem Label oder TextField.getText() funktioniert nicht.

Java:
public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("One.fxml"));
            Scene scene = new Scene(root);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}
Java:
public class ControllerOne {
   
    @FXML private Label label;
    @FXML private TextField textField;
    // ruft Methode in ControllerTwo auf
    @FXML
    private void toControllerTwo () throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Two.fxml"));
        loader.load();
        ControllerTwo controller = loader.getController();
        controller.createPopUp();
    }
    // wird von Methode im ControllerTwo aufgerufen
    public void changeLable () {
        System.out.println("Text Lable: " + label.getText()); // funktioniert
        label.setText(textField.getText()); // funktioniert nicht
        System.out.println("TF: " + textField.getText()); // getText() funktioniert nicht
    }
}
Java:
public class ControllerTwo {
    // wird von Methode in ControllerOne aufgerufen
    public void createPopUp () throws IOException {
        Stage stageTwo = new Stage();
        Parent root = FXMLLoader.load(getClass().getResource("Two.fxml"));
        Scene sceneTwo = new Scene(root);
        sceneTwo.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
        stageTwo.setScene(sceneTwo);
        stageTwo.show();
    }
    // ruft Methode in ControllerOne auf
    @FXML
    private void toControllerOne (ActionEvent event) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("One.fxml"));
        loader.load();
        ControllerOne controller = loader.getController();
        controller.changeLable();
       
        Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
        stage.close();
    }
}
 
wie viele controller ones brauchst du denn ?
Code:
 public void start(Stage primaryStage) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("One.fxml"));
            Scene scene = new Scene(root);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
Java:
    private void toControllerOne (ActionEvent event) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("One.fxml"));
        loader.load();
        ControllerOne controller = loader.getController();
        controller.changeLable();
      
        Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
        stage.close();
    }
würde es nicht reichen den aus der start methode herzunehmen ?
und es passiert exakt das was ich gesagt habe...
Code:
        FXMLLoader loader = new FXMLLoader(getClass().getResource("One.fxml"));
        loader.load();
        ControllerOne controller = loader.getController();
        controller.changeLable();
du baust dir einen NAGELNEUEN controller der nichts mit dem in start zu tun hat , wirfst die view sofort wieder weg

und schon klar ... das textfeld des gerade erzeugten controllers ist leer, hast du auch so eignestelllt in deiner fxml, nur du denkst du greifst auf den controller in der start methode zu, wo du den text rei ngeschrieben hast

aber das tust du nicht ... du machst einen nagelneuen controller wo du die view aus dem fenster wirfst

ich würde dir mal "empfehlen" sowas zu machen
Code:
    private void toControllerTwo () throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Two.fxml"));
        loader.load();
        ControllerTwo controller = loader.getController();
        // übergib dich selbst dem anderen controller dass der dich kennt
        controller.fuegeExternenControllerEin(this)
        controller.createPopUp();
    }
das fügst du in deinen controllertwo ein, somit kennt der auch den one jetzt... und auch den der ihn erzeugt hat
Java:
public class controllertwo...
    
    ControllerOne controllerOne;
public void fuegeExternenControllerEin(ControllerOne one)
{
    this.controllerOne = one;
}
so und das baust du dir selber die methode in controllerone rein dass das funtkioniert
Code:
    private void toControllerOne (ActionEvent event) throws IOException {
        this.controllerOne.ChangeLable();
    }
( deine toControllerone brauchst du nicht mehr dann )
 
wie viele controller ones brauchst du denn ?
Code:
 public void start(Stage primaryStage) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("One.fxml"));
            Scene scene = new Scene(root);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
Java:
    private void toControllerOne (ActionEvent event) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("One.fxml"));
        loader.load();
        ControllerOne controller = loader.getController();
        controller.changeLable();
     
        Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
        stage.close();
    }
würde es nicht reichen den aus der start methode herzunehmen ?
und es passiert exakt das was ich gesagt habe...
Code:
        FXMLLoader loader = new FXMLLoader(getClass().getResource("One.fxml"));
        loader.load();
        ControllerOne controller = loader.getController();
        controller.changeLable();
du baust dir einen NAGELNEUEN controller der nichts mit dem in start zu tun hat , wirfst die view sofort wieder weg

und schon klar ... das textfeld des gerade erzeugten controllers ist leer, hast du auch so eignestelllt in deiner fxml, nur du denkst du greifst auf den controller in der start methode zu, wo du den text rei ngeschrieben hast

aber das tust du nicht ... du machst einen nagelneuen controller wo du die view aus dem fenster wirfst

ich würde dir mal "empfehlen" sowas zu machen
Code:
    private void toControllerTwo () throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Two.fxml"));
        loader.load();
        ControllerTwo controller = loader.getController();
        // übergib dich selbst dem anderen controller dass der dich kennt
        controller.fuegeExternenControllerEin(this)
        controller.createPopUp();
    }
das fügst du in deinen controllertwo ein, somit kennt der auch den one jetzt... und auch den der ihn erzeugt hat
Java:
public class controllertwo...
   
    ControllerOne controllerOne;
public void fuegeExternenControllerEin(ControllerOne one)
{
    this.controllerOne = one;
}
so und das baust du dir selber die methode in controllerone rein dass das funtkioniert
Code:
    private void toControllerOne (ActionEvent event) throws IOException {
        this.controllerOne.ChangeLable();
    }
( deine toControllerone brauchst du nicht mehr dann )
Ist eine Gute Idee, habe es mal soweit umgesetzt, jedoch wird der ControllerOne in der Valiable nicht zwischengespeichert und gibt beim Aufruf in der Methode toControllerOne(); null zurück.
 
dürfte eig nicht sein ... zeig mal den code
Java:
public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("One.fxml"));
            Scene scene = new Scene(root);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}
Java:
public class ControllerOne {
   
    @FXML private Label label;
    @FXML private TextField textField;
   
    @FXML
    private void toControllerTwo () throws IOException {
       
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Two.fxml"));
        loader.load();
        ControllerTwo controller = loader.getController();
        controller.exController(this);
        controller.createPopUp();
        System.out.println(this);
    }
    @FXML
    public void changeLable () {
        System.out.println("Text Lable: " + label.getText()); 
        label.setText(textField.getText()); 
        System.out.println("TF: " + textField.getText());
    }
}
Java:
public class ControllerTwo {
   
    private ControllerOne ControllerOne;
   
   
    @FXML
    public void createPopUp () throws IOException {
        Stage stageTwo = new Stage();
        Parent root = FXMLLoader.load(getClass().getResource("Two.fxml"));
        Scene sceneTwo = new Scene(root);
        sceneTwo.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
        stageTwo.setScene(sceneTwo);
        stageTwo.show();
    }
   
    public void exController (ControllerOne one) {
        this.ControllerOne = one;
        System.out.println(one);
        System.out.println(this.ControllerOne); // funktioniert
    }
    @FXML
    private void toControllerOne () {
        System.out.println(this.ControllerOne); // funktioniert nicht

        this.ControllerOne.changeLable(); // hier: NullPointerEx. ControllerOne
    }
}
 
Zuletzt bearbeitet:
unter create pop up lädst du wieder einen neuen controllertwo der komplett neu ist und bei dem du niemals dne controllerone gesetzt hast... lass einfach das create popup

so zb wenn du ein neues fesnter willst
Java:
    @FXML
    private void toControllerTwo () throws IOException {
      
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Two.fxml"));
        ControllerTwo controller = loader.getController();
        controller.exController(this);

        Parent controllerTwoFxmlGuiRootElement = loader.load();
        
        // hier stage und scene bauen
        // new Scene(controllerTwoFxmlGuiRootElement);
        // stage.show
    }
lass den controller one eine stage und scene bauen, und in diese szene setzt du controllertwo ein

somit gehören "teile" aus create pop up einfach in controller one

du verstehst noch nicht was fxml macht denke ich...

du hast deine hierarchie von nodes
und fxml.load macht 2 sachen
die wandelt das xml zeug in javafx objekte um und baut einen teil des hierarchie baumes von nodes
diesen "teil baum" musst du in ein layout(hbox oder sonst was ) einsetzen oder in eine szene ansonsten siehst das nicht
das zweite was fxml tut ist es erzeugt das controller objekt was du in der fxml angegeben hast und übergibt den controller das @FXML zeug dass das funktioniert

wenn du nur fxml.load() machst dann hast du die aus fxm gebaute node hierarchie weggeworfen ( das wäre Parent rückgabe wert.. parent ist ein node der irgend ein javafx objekt ist ) und den controller raus genommen.. nur dir hilft der controller halt nix ohne die node hierarchie weil du schlichtweg das zeug nicht siehst...

es gibt momente wo man es braucht deswegen kannst du das parent root auch weglassen aber du brauchst es hier

meines wissens nach sollte fxmlload auch generisch sein udn du soltlest das root objekt angeben können wie zb hbox... aber javafx hat mich heute dezent angepisst ... um genau zu sein hat maven dann das fass zum überlaufen gebracht mit java 17.. von daher werd ich nicht nachschauen ob es generisch ist ...
var root = fxml.load<VBox>();
könnte es aussehen ... aber bin nicht sicher
 
unter create pop up lädst du wieder einen neuen controllertwo der komplett neu ist und bei dem du niemals dne controllerone gesetzt hast... lass einfach das create popup

so zb wenn du ein neues fesnter willst
Java:
    @FXML
    private void toControllerTwo () throws IOException {
     
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Two.fxml"));
        ControllerTwo controller = loader.getController();
        controller.exController(this);

        Parent controllerTwoFxmlGuiRootElement = loader.load();
       
        // hier stage und scene bauen
        // new Scene(controllerTwoFxmlGuiRootElement);
        // stage.show
    }
lass den controller one eine stage und scene bauen, und in diese szene setzt du controllertwo ein

somit gehören "teile" aus create pop up einfach in controller one

du verstehst noch nicht was fxml macht denke ich...

du hast deine hierarchie von nodes
und fxml.load macht 2 sachen
die wandelt das xml zeug in javafx objekte um und baut einen teil des hierarchie baumes von nodes
diesen "teil baum" musst du in ein layout(hbox oder sonst was ) einsetzen oder in eine szene ansonsten siehst das nicht
das zweite was fxml tut ist es erzeugt das controller objekt was du in der fxml angegeben hast und übergibt den controller das @FXML zeug dass das funktioniert

wenn du nur fxml.load() machst dann hast du die aus fxm gebaute node hierarchie weggeworfen ( das wäre Parent rückgabe wert.. parent ist ein node der irgend ein javafx objekt ist ) und den controller raus genommen.. nur dir hilft der controller halt nix ohne die node hierarchie weil du schlichtweg das zeug nicht siehst...

es gibt momente wo man es braucht deswegen kannst du das parent root auch weglassen aber du brauchst es hier

meines wissens nach sollte fxmlload auch generisch sein udn du soltlest das root objekt angeben können wie zb hbox... aber javafx hat mich heute dezent angepisst ... um genau zu sein hat maven dann das fass zum überlaufen gebracht mit java 17.. von daher werd ich nicht nachschauen ob es generisch ist ...

könnte es aussehen ... aber bin nicht sicher
Ja klasse, so funktioniert es. Auf jeden Fall vielen Dank für die ausführlichen Erklärungen. Und genau, ich hatte vor kurzem erst mit FXML gestartet, aber konnte aus diesem Beitrag wieder einiges Interessantes mitnehmen.
 

Zurück
Oben