如何临时从ChoiceBox(或ComboBox)中删除项目?

时间:2015-06-03 11:15:22

标签: combobox javafx scenebuilder

我遇到了一个有点令人困惑的难题。我最近开始弄清楚如何与听众合作,感谢这里的一些人,我试图找到一种方法将它们与选择/组合框一起使用来做一些棘手的事情。我想要发生的是,当用户从包含六个选项的六个链接框之一中进行选择时,它会从其他5个框中删除该选项,直到A:选项更改为其中一个选项,或者B :该选项被更改为空或默认设置(以防止获取"锁定在"选择后,或者我可以只为此目的制作一个重置按钮)。我现在在每个选项框上都有一个ChangeListener,但是我尝试了各种各样的事情(切换语句,为每个答案分配一个布尔值,各种尝试使用.getItems()。remove()徒劳,我&#39已经过了一段时间)有没有人想过或看过如何做到这一点的例子?提前感谢任何建议,你们(和女士们)在过去的几周里帮助我学会了跨越式发展。

1 个答案:

答案 0 :(得分:1)

如果你想要这样的东西:

enter image description here

我的程序中有这个代码。它也不是很有效,但对我来说只需要一小部分数据就可以了。

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ChoiceBox;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ConnectedComboBox<T> implements ChangeListener<T> {

    private ObservableList<T> items;
    private List<ChoiceBox<T>> comboBoxList = new ArrayList<>();

    public ConnectedComboBox(ObservableList<T> items){
        this.items = items;
        if (this.items == null) this.items = FXCollections.observableArrayList();
    }

    public void addComboBox(ChoiceBox<T> comboBox){
        comboBoxList.add(comboBox);
        comboBox.valueProperty().addListener(this);
        updateSelection();
    }

    public void removeComboBox(ChoiceBox<T> comboBox){
        comboBoxList.remove(comboBox);
        comboBox.valueProperty().removeListener(this);
        updateSelection();
    }

    // this boolean needed because we can set combobox Value in updateSelection() 
    // this will trigger a value listener and update selection one more time => stack overflow
    // this behavior occurs only if we have more than one equal item in source ObservableList<T> items list.
    private boolean updating = false;
    private void updateSelection() {
        if (updating) return;
        updating = true;

        List<T> availableChoices = items.stream().collect(Collectors.toList());
        for (ChoiceBox<T> comboBox: comboBoxList){
            if (comboBox.getValue()!= null) {
                availableChoices.remove(comboBox.getValue());
            }
        }

        for (ChoiceBox<T> comboBox: comboBoxList){
            T selectedValue = comboBox.getValue();
            ObservableList<T> items = comboBox.getItems();
            items.setAll(availableChoices);

            if (selectedValue != null) {
                items.add(selectedValue);
                comboBox.setValue(selectedValue);
            }
        }

        updating = false;
    }

    @Override
    public void changed(ObservableValue<? extends T> observable, T oldValue, T newValue) {
        updateSelection();
    }
}

以下是您使用它的方式:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class MainFX extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        HBox root = new HBox();
        root.setSpacing(10);
        ObservableList<String> values = FXCollections.observableArrayList("One", "Two", "Three", "Four","Five");
        ChoiceBox<String> combo1 = new ChoiceBox<>();
        combo1.setPrefWidth(100);
        ChoiceBox<String> combo2 = new ChoiceBox<>();
        combo2.setPrefWidth(100);
        ChoiceBox<String> combo3 = new ChoiceBox<>();
        combo3.setPrefWidth(100);
        root.getChildren().addAll(combo1,combo2,combo3);

        ConnectedComboBox<String> connectedComboBox = new ConnectedComboBox<>(values);
        connectedComboBox.addComboBox(combo1);
        connectedComboBox.addComboBox(combo2);
        connectedComboBox.addComboBox(combo3);

        primaryStage.setScene(new Scene(root,600,600));
        primaryStage.show();
    }

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