使用JavaFX创建2个相互依赖的下拉框的正确方法?

时间:2017-08-30 12:22:12

标签: java javafx combobox

我开始使用Java和JavaFX,对于我的第一个项目,我需要2个下拉框,A和B.当我从A中选择一个项目时,B中的内容会自动更改。我已经设法使用setOnAction,但我想知道是否有更好的方法来做到这一点。听众可能吗?我已经看了一下,但我不完全确定如何使用它们。

到目前为止,这是我的代码:

@Override
public void start(Stage primaryStage) {

    String[] mainlist = {"Selector A", "Selector B"};
    String[] options1 = {"Option 1", "Option 2", "Option 3"};
    String[] options2 = {"Option 4", "Option 5", "Option 6"};

    primaryStage.setTitle("UI Test");
    Group root = new Group();
    Scene scene = new Scene(root, 450, 450, Color.WHITE);

    TabPane tabPane = new TabPane();
    BorderPane mainPane = new BorderPane();

    mainPane.setCenter(tabPane);
    mainPane.prefHeightProperty().bind(scene.heightProperty());
    mainPane.prefWidthProperty().bind(scene.widthProperty());


    //Create Tab 1
    Tab tab1 = new Tab();
    tab1.setText("TestTab");
    tab1.setClosable(false);

    //Create grid1 and add it to Tab 1
    GridPane grid1 = new GridPane();
    grid1.setAlignment(Pos.BASELINE_LEFT);
    grid1.setHgap(5);
    grid1.setVgap(5);
    grid1.setPadding(new Insets(10, 10, 10, 10));
    grid1.getColumnConstraints().add(new ColumnConstraints(100));
    grid1.getColumnConstraints().add(new ColumnConstraints(300));

    tab1.setContent(grid1);
    tabPane.getTabs().add(tab1);

    //Add combobox1 to grid1
    grid1.add(new Label("Action:"), 0, 1); //Places label
    ObservableList<String> aComboList = FXCollections.observableArrayList();

    for (int i = 0; i < mainlist.length; i++){
        aComboList.add(mainlist[i]);
    }

    ComboBox<String> aBoxProjects = new ComboBox<String>(aComboList);
    grid1.add(aBoxProjects, 1, 1);


    //Add combobox2 to grid1
    grid1.add(new Label("Elements:"), 0, 2); //Places label
    ObservableList<String> bComboList = FXCollections.observableArrayList();
    ComboBox<String> bBoxProjects = new ComboBox<String>(bComboList);
    grid1.add(bBoxProjects, 1, 2);

    root.getChildren().add(mainPane);
    primaryStage.setScene(scene);
    primaryStage.show();


    aBoxProjects.setOnAction (new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent b) {

            bComboList.clear();

            if (aBoxProjects.getValue().toString() == mainlist[0]){
                for (int i = 0; i < options1.length; i++){
                    bComboList.add(options1[i]);
                }
            } else {
                for (int i = 0; i < options2.length; i++){
                    bComboList.add(options2[i]);
                }
            }

        }
    });

}

这只是一种初步方法。随着时间的推移,数组将被从文件读取的字符串等替换。现在我更关心正确使用JavaFX。有没有办法以更优雅的方式编写相同的代码?

谢谢!

1 个答案:

答案 0 :(得分:0)

您可以减少所拥有的代码量,并且仍然使用相同的基本策略:

ObservableList<String> aComboList = FXCollections.observableArrayList(mainlist);

ComboBox<String> aBoxProjects = new ComboBox<String>(aComboList);
grid1.add(aBoxProjects, 1, 1);


//Add combobox2 to grid1
grid1.add(new Label("Elements:"), 0, 2); //Places label

ObservableList<String> bComboList = FXCollections.observableArrayList();
ComboBox<String> bBoxProjects = new ComboBox<String>(bComboList);
grid1.add(bBoxProjects, 1, 2);

root.getChildren().add(mainPane);
primaryStage.setScene(scene);
primaryStage.show();


aBoxProjects.setOnAction (new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent b) {

        if (aBoxProjects.getValue().toString() == mainlist[0]){
            bcomboList.setAll(options1);
        } else {
            bcomboList.setAll(options2);
        }

    }
});

你可以使用lambda表达式代替匿名内部类:

aBoxProjects.setOnAction (b -> {
    if (aBoxProjects.getValue() == mainlist[0]){
        bcomboList.setAll(options1);
    } else {
        bcomboList.setAll(options2);
    }
});

甚至

aBoxProjects.setOnAction(b -> 
    bcomboList.setAll(aBoxProjects.getValue() == mainlist[0] ? options1 : options2));

您也可以使用绑定而不是使用事件处理程序:

ObservableList<String> aComboList = FXCollections.observableArrayList(mainlist);

ComboBox<String> aBoxProjects = new ComboBox<String>(aComboList);
grid1.add(aBoxProjects, 1, 1);


//Add combobox2 to grid1
grid1.add(new Label("Elements:"), 0, 2); //Places label
ObservableList<String> bComboList1 = FXCollections.observableArrayList(options1);
ObservableList<String> bComboList2 = FXCollections.observableArrayList(options2);
ComboBox<String> bBoxProjects = new ComboBox<String>();
grid1.add(bBoxProjects, 1, 2);

bBoxProjects.itemsProperty().bind(Bindings.createObjectBinding(() -> {
    if (aBoxProject.getValue() ==  mainlist[0]) {
        return bComboList1 ;
    } else if (aBoxProject.getValue() == mainlist[1]) {
        return bComboList2 ;
    } else { // no selection
        return FXCollections.emptyObservableList();
    }
}, aBoxProject.valueProperty()));       

root.getChildren().add(mainPane);
primaryStage.setScene(scene);
primaryStage.show();