0

I have two javaFx window. The first has a ComboBox and a Button to open second modal window.

In second window have a TextField and a Button Control to add the textField value to MainController Window's ComboBox. I am not getting any idea that how to do it. With a explained Example would great helpful for me. Below is the classes:

Main.java

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    }


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

Contrller.java

package sample;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.stage.Modality;
import javafx.stage.Stage;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable{
    @FXML
    public ComboBox<String> combo;
    @FXML
    Button button;
    public ObservableList<String> list = FXCollections.observableArrayList("A");
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        setCombo();

    }

    public void setCombo(){
        combo.setItems(list);
    }

    public void openModal() throws IOException {
        Stage primaryStage = new Stage();
        Parent root = FXMLLoader.load(getClass().getResource("sec.fxml"));
        primaryStage.setTitle("Send Mail");
        primaryStage.setScene(new Scene(root,800,600));
        primaryStage.initModality(Modality.WINDOW_MODAL);
        //primaryStage.initOwner((Stage) menuBar.getScene().getWindow());
        primaryStage.show();
    }
}

FXML for Main Window:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>

<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
    <children>
        <StackPane prefHeight="67.0" prefWidth="600.0">
            <children>
                <Label text="Get value from Another Child Dialog" />
            </children>
        </StackPane>
        <HBox prefHeight="100.0" prefWidth="200.0">
            <children>
                <Label text="Add Value of TextBox:" />
                <ComboBox fx:id="combo" prefWidth="150.0" />
            </children>
        </HBox>
        <Button fx:id="button" mnemonicParsing="false" onAction="#openModal" text="Open Dialog" />
    </children>
</VBox>

Now Second window Sec.Java

package sample;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;

import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;

/**
* Created by tracedot on 12/11/16.
*/
public class Sec implements Initializable{
    @FXML
    Button button;
    @FXML
    TextField textfield;
    public Controller controller=new Controller();

    public void setToCombo(){
        String cbvalue= textfield.getText();
        controller.combo.getItems().add(cbvalue);
        //controller.combo.itemsProperty().setValue(new ArrayList<String>().add());
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        //setToCombo();

    }
}

Second window FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>

<HBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Sec">
    <children>
        <TextField fx:id="textfield" />
        <Button fx:id="button" mnemonicParsing="false" onAction="#setToCombo" text="Add to Combo" />
    </children>
</HBox>
fabian
  • 80,457
  • 12
  • 86
  • 114
u4547878
  • 197
  • 4
  • 13
  • Possible duplicate of [Passing Parameters JavaFX FXML](http://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml) – Omid Dec 11 '16 at 09:30
  • Also related: http://stackoverflow.com/questions/40117925/javafx-many-static-fxml-controllers/40353976#40353976 – Omid Dec 11 '16 at 09:33

1 Answers1

1

Creating a new instance of the Controller class also used for the main fxml won't help you communicate with the instance used with the fxml displayed. You have to pass the existing controller to the Sec instance used with the second fxml:

public class Sec implements Initializable{

    ...

    private Controller controller;

    public void setController(Controller controller ) {
        this.controller = controller;
    }

    ...

}
public void openModal() throws IOException {
    Stage primaryStage = new Stage();
    FXMLLoader loader = new FXMLLoader(getClass().getResource("sec.fxml"));
    Parent root = loader.load();
    primaryStage.setTitle("Send Mail");
    primaryStage.setScene(new Scene(root,800,600));
    primaryStage.initModality(Modality.WINDOW_MODAL);
    //primaryStage.initOwner((Stage) menuBar.getScene().getWindow());

    loader.<Sec>getController().setController(this);
    primaryStage.show();
}

In case you want to close the new window after the input, you can also use showAndWait() to display the new stage:

public class Sec implements Initializable{

    ...
    private String result = null;

    public String getResult() {
        return result;
    }

    public void setCombo() {
        result = textfield.getText();
        textField.getScene().getWindow().hide();
    }

    ...

}
public void openModal() throws IOException {
    Stage primaryStage = new Stage();
    FXMLLoader loader = new FXMLLoader(getClass().getResource("sec.fxml"));
    Parent root = loader.load();
    primaryStage.setTitle("Send Mail");
    primaryStage.setScene(new Scene(root,800,600));
    primaryStage.initModality(Modality.WINDOW_MODAL);
    //primaryStage.initOwner((Stage) menuBar.getScene().getWindow());

    primaryStage.showAndWait();

    String result = loader.<Sec>getController().getResult();

    if (result != null) {
        // if a result was selected, add it to the list
        list.add(result);
    }
}

Note that with this approach, if you want to reuse the second scene you also should add some functionality to reset the result field.

fabian
  • 80,457
  • 12
  • 86
  • 114
  • 1
    Seems a bit complicated as i am still new to java. But it works and i will study it to see how it is actually works. – u4547878 Dec 12 '16 at 08:16
  • If don't use the textField.getScene().getWindow().hide(); then it some times don't add some items. – u4547878 Dec 12 '16 at 08:29