I'm currently trying to figure out how to implement a feature in which the user clicks a button and a popup appears, and then the user enters data into that popup, clicks a confirm button, and the data becomes visible in the popups owner. I was able to make data from the owner stage carry over to the popup stage after follow Bro Code's tutorial on making controllers communicate, however getting it to work the other way around is proving troublesome. Below is a project in which I've isolated the issue to try and figure it out.
App.java
package org.example;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.util.Objects;
public class App extends Application {
public static Stage stage;
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getResource("primary.fxml")));
Scene scene = new Scene(root);
stage = new Stage();
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
PrimaryController.java
package org.example;
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class PrimaryController {
@FXML
Label label;
@SuppressWarnings("unused")
public void login(ActionEvent event) throws IOException{
FXMLLoader loader = new FXMLLoader(getClass().getResource("secondary.fxml"));
Parent root = loader.load();
SecondaryController secondaryController = loader.getController();
secondaryController.stage = new Stage();
secondaryController.stage.initModality(Modality.APPLICATION_MODAL);
secondaryController.stage.initOwner(App.stage);
Scene scene = new Scene(root);
secondaryController.stage.setScene(scene);
secondaryController.stage.show();
}
public void displayMessage(String message){
label.setText(message);
}
}
SecondaryController.java
package org.example;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import java.io.IOException;
public class SecondaryController {
@FXML
TextField textField;
public Stage stage;
@SuppressWarnings("unused")
public void writeToOwner(ActionEvent event) throws IOException {
String message = textField.getText();
FXMLLoader loader = new FXMLLoader(getClass().getResource("primary.fxml"));
Parent root = loader.load();
PrimaryController primaryController = loader.getController();
primaryController.displayMessage(message);
stage.close();
}
}
primary.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.PrimaryController">
<children>
<Button layoutX="270.0" layoutY="230.0" mnemonicParsing="false" onAction="#login" text="Login" />
<Label fx:id="label" layoutX="280.0" layoutY="191.0" />
</children>
</AnchorPane>
secondary.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.SecondaryController">
<children>
<TextField fx:id="textField" layoutX="219.0" layoutY="187.0" onAction="#writeToOwner" />
</children>
</AnchorPane>
The current behavior that I get from this code is almost what I want, except when the user would submit the text, it closes the popup but doesn't change the popups owner.