JavaFX:当将新项添加到child-window-ComboBox时,在parent-window-ComboBox中添加项

时间:2017-01-27 12:18:00

标签: javafx combobox binding

使用例

父窗口包含顶部的菜单栏,它有一个菜单(例如数据),该菜单只包含一个菜单项(例如导入)。当用户选择“导入”菜单项时,会出现一个对话窗口。父窗口中还有一个comboBox。

对话窗口有comboBox,textField和一个按钮。一旦用户在textField中输入任何文本并单击该按钮,该文本(如fruit-name)将被添加到comboBox中。还有另一个按钮可以关闭对话框(这里不重要)。

我正在尝试在将新项目添加到对话框窗口的组合框中时自动在父窗口的组合框中添加新项目,但我无法获得所需的结果。我没有找到任何comboBox属性,其中绑定可以是任何帮助(没有彻底探讨)。

我是JavaFX的新手,所以如果您在下面的代码中发现任何差距(除了无效的功能之外),请帮助我正确的编码实践。

Main.java (包:问题)

    package problem;

    import java.io.IOException;
    import javafx.application.Application;
    import javafx.stage.Stage;

    public class Main extends Application {

        @Override
        public void start(Stage primaryStage) throws IOException {
            MainWindowController mwc = new MainWindowController();
            mwc.launchMainWindow(primaryStage);
        }

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

MainWindow.fxml (包:问题)

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

    <?import javafx.scene.control.ComboBox?>
    <?import javafx.scene.control.Menu?>
    <?import javafx.scene.control.MenuBar?>
    <?import javafx.scene.control.MenuItem?>
    <?import javafx.scene.layout.VBox?>

    <VBox prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.102" xmlns:fx="http://javafx.com/fxml/1" fx:controller="problem.MainWindowController">
       <children>
          <MenuBar>
            <menus>
              <Menu text="Data">
                <items>
                  <MenuItem fx:id="importMenuItem" onAction="#launchImportDialog" text="Import" />
                </items>
              </Menu>
            </menus>
          </MenuBar>
          <ComboBox fx:id="fruitsComboBox" prefWidth="150.0" />
       </children>
    </VBox>

MainWindowController.java (包:问题)

    package problem;

    import java.io.IOException;
    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.collections.ObservableList;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.fxml.Initializable;
    import javafx.scene.Scene;
    import javafx.scene.control.ComboBox;
    import javafx.scene.control.MenuItem;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    import problem.importdata.ImportDataController;

    public class MainWindowController implements Initializable {
        private Stage primaryStage;
        @FXML
        private MenuItem importMenuItem;
        @FXML
        private ComboBox fruitsComboBox;

        @Override
        public void initialize(URL location, ResourceBundle resources) {
        }

        public void launchMainWindow(Stage primaryStage) throws IOException {
            this.primaryStage = primaryStage;
            FXMLLoader loader = new FXMLLoader(Main.class.getResource("MainWindow.fxml"));
            VBox root = loader.load();
            Scene scene = new Scene(root, 600, 400);

            primaryStage.setTitle("Problem");
            primaryStage.setScene(scene);
            primaryStage.show();
        }

        @FXML
        private void launchImportDialog() throws IOException {
            new ImportDataController().launchImportDialog(primaryStage);
        }

        @FXML
        public void addFruitsComboBox(String fruit) {
            ObservableList<String> fruitsList = fruitsComboBox.getItems();
            fruitsList.add(fruit);
            fruitsComboBox.setItems(fruitsList);
        }
    }

ImportData.fxml (包:problem.importdata)

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

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

    <VBox prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.102" xmlns:fx="http://javafx.com/fxml/1" fx:controller="problem.importdata.ImportDataController">
       <children>
          <HBox alignment="TOP_CENTER">
             <children>
                <ComboBox fx:id="fruitsComboBox" prefWidth="150.0" />
             </children>
          </HBox>
          <HBox alignment="TOP_CENTER">
             <children>
                <TextField fx:id="fruitTextField" />
                <Button fx:id="addFruitButton" onAction="#onClickAddFruitBtn" text="Add Fruit" />
             </children>
          </HBox>
          <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
             <children>
                <Button fx:id="closeButton" onAction="#onClickCloseBtn" text="Close" />
             </children>
          </HBox>
       </children>
    </VBox>

ImportDataController.java (包:problem.importdata)

    package problem.importdata;

    import java.io.IOException;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.ComboBox;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.VBox;
    import javafx.stage.Modality;
    import javafx.stage.Stage;
    import problem.MainWindowController;
    import problem.Main;

    public class ImportDataController {
        private Stage primaryStage;
        @FXML
        private ComboBox fruitsComboBox;
        @FXML
        private TextField fruitTextField;
        @FXML
        private Button addFruitButton;
        @FXML
        private Button closeButton;

        public void launchImportDialog(Stage primaryStage) throws IOException {
            this.primaryStage = primaryStage;
            FXMLLoader loader = new FXMLLoader(Main.class.getResource("importdata/ImportData.fxml"));
            VBox root = loader.load();
            Scene scene = new Scene(root, 400, 300);
            Stage stage = new Stage();
            stage.initModality(Modality.WINDOW_MODAL);
            stage.initOwner(primaryStage);
            stage.setTitle("Import");
            stage.setScene(scene);
            stage.showAndWait();
        }

        @FXML
        private void onClickCloseBtn() throws IOException {
            Stage stage = (Stage) closeButton.getScene().getWindow();
    stage.close();
        }

        @FXML
        private void onClickAddFruitBtn() throws IOException {
            String fruit = fruitTextField.getText();
            fruitsComboBox.getItems().add(fruit);
            fruitTextField.clear();

            // Trying to add fruit data in main windows combo box but it is not working
            FXMLLoader loader = new FXMLLoader(Main.class.getResource("MainWindow.fxml"));
            VBox root = loader.load();
            MainWindowController mwc = loader.<MainWindowController>getController();
            mwc.addFruitsComboBox(fruit);
        }
    }

1 个答案:

答案 0 :(得分:1)

// Trying to add fruit data in main windows combo box but it is not working
FXMLLoader loader = new FXMLLoader(Main.class.getResource("MainWindow.fxml"));
VBox root = loader.load();
MainWindowController mwc = loader.<MainWindowController>getController();
mwc.addFruitsComboBox(fruit);

它不起作用,因为您没有访问已存在的控制器,而是创建了一个新实例。

在控制器之间共享数据可以通过多种方式完成,在您的情况下,我相信,只需将ComboBox项目列表的引用传递给您的ImportDataController即可。你通过Stage的同样方式。

new ImportDataController().launchImportDialog(primaryStage, fruitsComboBox.getItems());

以简单的方式进行操作是有道理的,因为有问题的控制器的作用是明确定义的 - 它导入了水果,因此需要更新数据模型。

如果您的控制器更复杂,这种方法由于显而易见的原因会很糟糕。你真的不想保持冗长而混乱的参数列表。