user1563721
user1563721

Reputation: 1561

Java FX change Label text in a previous stage scene

I have a Main class starting my application which has its MainController class specified in fxml. When clicking on Connect button another windows with different scene and controller is opened. Based on action I would like to change Label text value through my MainController, but it does not work as expected. See details below.

Basically I would like to update text on connectedLabel in MainController class from ConnectController class and it does not work.

Main.java:

public class Main extends Application {

    private static final Logger logger = Logger.getLogger(Main.class.getName());

    @Override
    public void start(Stage primaryStage) {
        try {
            logger.info("Application is starting");
            AnchorPane page = FXMLLoader.load(getClass().getResource("Main.fxml"));

            //BorderPane root = new BorderPane();
            //Scene scene = new Scene(root,400,400);

            Scene scene = new Scene(page);
            scene.getStylesheets().add(getClass().getResource("Main.css").toExternalForm());
            primaryStage.setScene(scene);

            primaryStage.setResizable(false);

            primaryStage.show();

        } catch(Exception e) {
            logger.warning(e.getMessage());
        }
    }

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

}

MainController.java:

    public class MainController implements Initializable {

    private Context context = null;

    @FXML
    Label connectedLabel;
    @FXML
    Button connectButton;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        context = Context.getInstance();
    }

    public void setConnectedLabel(String name) {
        connectedLabel.setText(name);
        connectButton.setText("Disconnect");
    }

    @FXML
    public void connectTokenButton_onMouseClicked() {
        try {
            if (connectTokenButton.getText().equals("Disconnect")) {
                boolean disconnected = context.getToken().disconnectToken();
                if (disconnected) {
                    Alert alert = new Alert(AlertType.INFORMATION);
                    alert.setTitle("Disconnected");
                    alert.setHeaderText(null);
                    alert.setContentText("Succcessfully disconnected!");

                    alert.showAndWait();

                    connectedTokenLabel.setText("N/A");
                    connectTokenButton.setText("Connect");
                }
            } else {
                AnchorPane page = FXMLLoader.load(getClass().getResource("ConnectView.fxml"));

                Stage stage = new Stage();

                Scene scene = new Scene(page);
                scene.getStylesheets().add(getClass().getResource("ConnectView.css").toExternalForm());
                stage.setScene(scene);

                stage.setResizable(false);
                stage.initModality(Modality.APPLICATION_MODAL);
                stage.initOwner(connectedLabel.getScene().getWindow());
                stage.show();

                //Stage thisStage = (Stage) connectedTokenLabel.getScene().getWindow();
                //thisStage.close();
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

ConnectController.java:

public class ConnectController implements Initializable {

    private Context context = null;

    @FXML
    ComboBox<String> selectComboBox;
    @FXML
    PasswordField userPinPasswordField;
    @FXML
    Button cancelButton;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        context = Context.getInstance();
    }

    public void setMainC(Stage stage) {
        mainStage = stage;
    }

    @FXML
    private void connectToken_onMouseClicked() {
        String pin = userPinPasswordField.getText();
        boolean connected = context.connect(selectComboBox.getValue(), pin);        
        if (connected) {

            Alert alert = new Alert(AlertType.INFORMATION);
            alert.setTitle("Connected");
            alert.setHeaderText(null);
            alert.setContentText("Succcessfully connected!");

            alert.showAndWait();

            FXMLLoader myLoader = new FXMLLoader(getClass().getResource("Main.fxml"));
            MainController mainController = myLoader.getController();
            mainController.setConnectedTokenLabel(context.getConnectedName());

            Stage thisStage = (Stage) selectComboBox.getScene().getWindow();
            thisStage.close();
        }
    }
}

What I am doing wrong when calling setConnectedLabel method from different controller?

Upvotes: 2

Views: 1598

Answers (1)

fabian
fabian

Reputation: 82461

FXMLLoader myLoader = new FXMLLoader(getClass().getResource("Main.fxml"));
MainController mainController = myLoader.getController();
mainController.setConnectedTokenLabel(context.getConnectedName());

Without calling the load method of the FXMLLoader, no controller instance is created, even if the fx:controller attribute is specified in the fxml file.

However calling load before getController will not help, since the fxml is just loaded again with a different controller instance.

You need to "tell" the ConnectController about the MainController it was created from. (see Passing Parameters JavaFX FXML)

One way would be to add this code to the ConnectController class

private MainController mainController;

public void setMainController(MainController mainController) {
    this.mainController = mainController;
}

and use this field instead of the local variable in the connectToken_onMouseClicked() method.

To call the setter, access the controller after loading the view in connectTokenButton_onMouseClicked():

FXMLLoader loader = new FXMLLoader(getClass().getResource("ConnectView.fxml"));
AnchorPane page = loader.load();
loader.<ConnectController>getController().setMainController(this);

Upvotes: 2

Related Questions