带有复选框的JavaFX组合框 问题说明

带有复选框的JavaFX组合框 问题说明,java,checkbox,combobox,javafx,Java,Checkbox,Combobox,Javafx,我尝试创建一个JavaFX组合框,其中包含下拉菜单中的复选框。 组合框应是可编辑的,并由一个简单的类提供。 检查项列表应可检查,且在选择后不得关闭下拉菜单 最后,组合框中的文本应可用,并有一个选项(所有选中项) 这是我已经做过的 (1) 一个组合框通过正确选择将检查项呈现为检查框 (2) 从组合框中获取文本 出现的问题 (1) 单击一个项目后,下拉列表关闭,项目的选择状态不变 (2) 据我所知,一次只能选择一个项目 下面是我测试这些东西的代码: 测试程序 如果您在实现中遇到问题,您应该查看项目中

我尝试创建一个
JavaFX
组合框
,其中包含下拉菜单中的
复选框
组合框应是可编辑的,并由一个简单的
类提供。
检查项列表应可检查,且在选择后不得关闭下拉菜单

最后,
组合框
中的文本应可用,并有一个选项(所有选中项)

这是我已经做过的 (1) 一个
组合框
通过正确选择将
检查项
呈现为
检查框

(2) 从
组合框中获取文本

出现的问题 (1) 单击一个项目后,下拉列表关闭,项目的选择状态不变

(2) 据我所知,一次只能选择一个项目

下面是我测试这些东西的代码:

测试程序
如果您在实现中遇到问题,您应该查看项目中的控件

可以找到源代码。

我的示例代码:

班级人员

public class Person {

    private StringProperty name = new SimpleStringProperty();
    private ObjectProperty<LocalDate> birthday = new SimpleObjectProperty<>();

    public Person() {
    }

    public Person(String name, LocalDate birthday) {
        setNameValue(name);
        setBirthdayValue(birthday);
    }

    public StringProperty getNameProperty() {
        return name;
    }

    public String getNameValue() {
        return name.getValue();
    }

    public void setNameValue(String value) {
        name.setValue(value);
    }

    public ObjectProperty<LocalDate> getBirthdayProperty() {
        return birthday;
    }

    public LocalDate getBirthdayValue() {
        return birthday.getValue();
    }

    public void setBirthdayValue(LocalDate value) {
        birthday.setValue(value);
    }

    @Override
    public String toString() {
        return getNameValue()+" ("+getBirthdayValue()+")";
    }

}
公共类人物{
私有StringProperty名称=新的SimpleStringProperty();
private ObjectProperty生日=新的SimpleObjectProperty();
公众人士(){
}
公众人物(字符串名称、LocalDate生日){
setNameValue(名称);
setBirthdayValue(生日);
}
公共StringProperty getNameProperty(){
返回名称;
}
公共字符串getNameValue(){
返回name.getValue();
}
公共void setNameValue(字符串值){
name.setValue(值);
}
公共对象属性getBirthdayProperty(){
回归生日;
}
public LocalDate getBirthdayValue(){
返回birthday.getValue();
}
public void setBirthdayValue(LocalDate值){
生日设置值(value);
}
@凌驾
公共字符串toString(){
返回getNameValue()+”(“+getBirthdayValue()+”);
}
}
简单包装器

public class ComboBoxItemWrap<T> {

    private BooleanProperty check = new SimpleBooleanProperty(false);
    private ObjectProperty<T> item = new SimpleObjectProperty<>();

    ComboBoxItemWrap() {
    }

    ComboBoxItemWrap(T item) {
        this.item.set(item);
    }

    ComboBoxItemWrap(T item, Boolean check) {
        this.item.set(item);
        this.check.set(check);
    }

    public BooleanProperty checkProperty() {
        return check;
    }

    public Boolean getCheck() {
        return check.getValue();
    }

    public void setCheck(Boolean value) {
        check.set(value);
    }

    public ObjectProperty<T> itemProperty() {
        return item;
    }

    public T getItem() {
        return item.getValue();
    }

    public void setItem(T value) {
        item.setValue(value);
    }

    @Override
    public String toString() {
        return item.getValue().toString();
    }
}
公共类ComboBoxItemWrap{
私有布尔属性检查=新的SimpleBoleanProperty(false);
private ObjectProperty项=新的SimpleObject属性();
ComboBoxItemWrap(){
}
ComboBoxItemWrap(T项){
本.项.集(项);
}
ComboBoxItemWrap(T项,布尔检查){
本.项.集(项);
这个.检查.设置(检查);
}
公共布尔属性checkProperty(){
退货检查;
}
公共布尔getCheck(){
返回check.getValue();
}
公共void setCheck(布尔值){
检查。设置(值);
}
公共对象属性itemProperty(){
退货项目;
}
公共T getItem(){
return item.getValue();
}
公共无效设置项(T值){
项目.设置值(值);
}
@凌驾
公共字符串toString(){
返回item.getValue().toString();
}
}
示例代码

public class MainApplication extends Application {

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new VBox(), 450, 250);

        ComboBox<ComboBoxItemWrap<Person>> cb = new ComboBox<>();

        @SuppressWarnings("unchecked")
        ObservableList<ComboBoxItemWrap<Person>> options = FXCollections.observableArrayList(
                new ComboBoxItemWrap<>(new Person("A", LocalDate.now().minusDays(12))),
                new ComboBoxItemWrap<>(new Person("B", LocalDate.now().minusDays(34))),
                new ComboBoxItemWrap<>(new Person("C", LocalDate.now().minusDays(48))),
                new ComboBoxItemWrap<>(new Person("D", LocalDate.now().minusDays(56))),
                new ComboBoxItemWrap<>(new Person("E", LocalDate.now().minusDays(72))),
                new ComboBoxItemWrap<>(new Person("F", LocalDate.now().minusDays(96)))
                );

        cb.setCellFactory( c -> {
            ListCell<ComboBoxItemWrap<Person>> cell = new ListCell<>(){
                @Override
                protected void updateItem(ComboBoxItemWrap<Person> item, boolean empty) {
                    super.updateItem(item, empty);
                    if (!empty) {
                        final CheckBox cb = new CheckBox(item.toString());
                        cb.selectedProperty().bind(item.checkProperty());
                        setGraphic(cb);
                    }
                }
            };

            cell.addEventFilter(MouseEvent.MOUSE_RELEASED, event -> {
                cell.getItem().checkProperty().set(!cell.getItem().checkProperty().get());
                StringBuilder sb = new StringBuilder();
                cb.getItems().filtered( f-> f!=null).filtered( f-> f.getCheck()).forEach( p -> {
                    sb.append("; "+p.getItem());
                });
                final String string = sb.toString();
                cb.setPromptText(string.substring(Integer.min(2, string.length())));
            });

            return cell;
        });

        cb.setItems(options);


        VBox root = (VBox) scene.getRoot();

        Button bt = new Button("test");

        bt.setOnAction(event -> {
            cb.getItems().filtered( f -> f.getCheck()).forEach( item -> System.out.println(item.getItem()));
        });

        root.getChildren().addAll(cb, bt);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
public类main应用程序扩展应用程序{
@凌驾
公众假期开始(阶段){
场景=新场景(新VBox(),450,250);
ComboBox cb=新ComboBox();
@抑制警告(“未选中”)
ObservableList options=FXCollections.observableArrayList(
新的ComboBoxItemWrap(newPerson(“A”,LocalDate.now().minusDays(12)),
新的ComboBoxItemWrap(newPerson(“B”,LocalDate.now().minusDays(34)),
新建ComboBoxItemWrap(newPerson(“C”,LocalDate.now().minusDays(48)),
新建ComboxItemWrap(newPerson(“D”,LocalDate.now().minusDays(56)),
新的ComboBoxItemWrap(newPerson(“E”,LocalDate.now().minusDays(72)),
新ComboBoxItemWrap(newPerson(“F”,LocalDate.now().minusDays(96)))
);
cb.setCellFactory(c->{
ListCell=新ListCell(){
@凌驾
受保护的void updateItem(ComboBoxItemWrap项,布尔值为空){
super.updateItem(项,空);
如果(!空){
最终复选框cb=新复选框(item.toString());
cb.selectedProperty().bind(item.checkProperty());
设定图形(cb);
}
}
};
cell.addEventFilter(MouseEvent.MOUSE_已发布,事件->{
cell.getItem().checkProperty().set(!cell.getItem().checkProperty().get());
StringBuilder sb=新的StringBuilder();
cb.getItems().filtered(f->f!=null).filtered(f->f.getCheck()).forEach(p->{
sb.append(“;”+p.getItem());
});
最后一个字符串=sb.toString();
setPrompText(string.substring(Integer.min(2,string.length()));
});
返回单元;
});
cb.设置项目(选项);
VBox root=(VBox)scene.getRoot();
按钮bt=新按钮(“测试”);
bt.setOnAction(事件->{
cb.getItems().filtered(f->f.getCheck()).forEach(item->System.out.println(item.getItem());
});
root.getChildren().addAll(cb,bt);
舞台场景;
stage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}

组合框
es专门用于从项目列表中选择一个项目。我想对于你想要的功能,我会从一个填充的开始。项目中还有一个你可能想看看。谢谢JoséPereda,不知怎么的,我错过了这个!你能加上这个作为回答来接受它吗?谢谢你好如何将此复选框添加到FXML文件中?请创建一个新问题。
public class ComboBoxItemWrap<T> {

    private BooleanProperty check = new SimpleBooleanProperty(false);
    private ObjectProperty<T> item = new SimpleObjectProperty<>();

    ComboBoxItemWrap() {
    }

    ComboBoxItemWrap(T item) {
        this.item.set(item);
    }

    ComboBoxItemWrap(T item, Boolean check) {
        this.item.set(item);
        this.check.set(check);
    }

    public BooleanProperty checkProperty() {
        return check;
    }

    public Boolean getCheck() {
        return check.getValue();
    }

    public void setCheck(Boolean value) {
        check.set(value);
    }

    public ObjectProperty<T> itemProperty() {
        return item;
    }

    public T getItem() {
        return item.getValue();
    }

    public void setItem(T value) {
        item.setValue(value);
    }

    @Override
    public String toString() {
        return item.getValue().toString();
    }
}
public class MainApplication extends Application {

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new VBox(), 450, 250);

        ComboBox<ComboBoxItemWrap<Person>> cb = new ComboBox<>();

        @SuppressWarnings("unchecked")
        ObservableList<ComboBoxItemWrap<Person>> options = FXCollections.observableArrayList(
                new ComboBoxItemWrap<>(new Person("A", LocalDate.now().minusDays(12))),
                new ComboBoxItemWrap<>(new Person("B", LocalDate.now().minusDays(34))),
                new ComboBoxItemWrap<>(new Person("C", LocalDate.now().minusDays(48))),
                new ComboBoxItemWrap<>(new Person("D", LocalDate.now().minusDays(56))),
                new ComboBoxItemWrap<>(new Person("E", LocalDate.now().minusDays(72))),
                new ComboBoxItemWrap<>(new Person("F", LocalDate.now().minusDays(96)))
                );

        cb.setCellFactory( c -> {
            ListCell<ComboBoxItemWrap<Person>> cell = new ListCell<>(){
                @Override
                protected void updateItem(ComboBoxItemWrap<Person> item, boolean empty) {
                    super.updateItem(item, empty);
                    if (!empty) {
                        final CheckBox cb = new CheckBox(item.toString());
                        cb.selectedProperty().bind(item.checkProperty());
                        setGraphic(cb);
                    }
                }
            };

            cell.addEventFilter(MouseEvent.MOUSE_RELEASED, event -> {
                cell.getItem().checkProperty().set(!cell.getItem().checkProperty().get());
                StringBuilder sb = new StringBuilder();
                cb.getItems().filtered( f-> f!=null).filtered( f-> f.getCheck()).forEach( p -> {
                    sb.append("; "+p.getItem());
                });
                final String string = sb.toString();
                cb.setPromptText(string.substring(Integer.min(2, string.length())));
            });

            return cell;
        });

        cb.setItems(options);


        VBox root = (VBox) scene.getRoot();

        Button bt = new Button("test");

        bt.setOnAction(event -> {
            cb.getItems().filtered( f -> f.getCheck()).forEach( item -> System.out.println(item.getItem()));
        });

        root.getChildren().addAll(cb, bt);
        stage.setScene(scene);
        stage.show();
    }

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