带有复选框的 JavaFX 组合框
Posted
技术标签:
【中文标题】带有复选框的 JavaFX 组合框【英文标题】:JavaFX ComboBox with CheckBoxes 【发布时间】:2014-12-25 04:45:17 【问题描述】:问题描述
我尝试创建一个JavaFX
ComboBox
,它在下拉菜单中保存CheckBoxes
。
ComboBox
应该是可编辑的,并由一个简单的Class
提供,我们称之为CheckItem
。
CheckItems
的列表应该是可检查的 - 并且在做出选择后不应关闭下拉菜单。
最后,ComboBox
中的文本应该可用并且选择(所有选中项)
这是我已经解决的问题
(1) ComboBox
将 CheckItem
渲染为 CheckedBox
并正确选择
(2) 从ComboBox
获取文本
出现的问题
(1) 点击一个项目后,下拉菜单关闭并且项目的选择状态不会改变。
(2) 据我所知,一次只能选择 一个 项?
这是我测试这些东西的代码:
测试程序
public class ComboButtonSample extends Application
@Override
public void start(Stage stage)
final ObservableList<CheckItem> items = fetchItems();
ComboBox<CheckItem> combo = createComboBox(items);
combo.setPromptText("enter searchstring here");
combo.setEditable(true);
// order the components vertically
VBox vBox = new VBox();
vBox.getChildren().add(combo);
// Button to write out the text and the items of the combobox
Button btn = new Button();
btn.setText("combo text to console");
btn.setOnAction((event) ->
System.out.println("Text is: "+combo.getEditor().getText());
System.out.println("Content is: ");
for (Iterator<CheckItem> iterator = combo.getItems().iterator(); iterator.hasNext();)
CheckItem ci = (CheckItem) iterator.next();
System.out.println(String.format("[%s] %s -> %s", ci.selected ? "X" : " ",ci.getDisplayName(), ci.getInternalName()));
);
vBox.getChildren().add(btn);
// show you do not need any code to change the selection of the box.
CheckBox checkBox = new CheckBox();
checkBox.setText("test box");
vBox.getChildren().add(checkBox);
stage.setScene(new Scene(vBox));
stage.show();
private ComboBox<CheckItem> createComboBox(ObservableList<CheckItem> data)
ComboBox<CheckItem> combo = new ComboBox<>();
combo.getItems().addAll(data);
combo.setCellFactory(listView -> new CheckItemListCell());
return combo;
class CheckItemListCell extends ListCell<CheckItem>
private final CheckBox btn;
CheckItemListCell()
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
btn = new CheckBox();
@Override
protected void updateItem(CheckItem item, boolean empty)
super.updateItem(item, empty);
if (item == null || empty)
setGraphic(null);
else
btn.setText(item.getDisplayName());
btn.selectedProperty().setValue(item.selected);
setGraphic(btn);
private ObservableList<CheckItem> fetchItems()
final ObservableList<CheckItem> data = FXCollections
.observableArrayList();
for (int i = 1; i < 15; i++)
CheckItem chkItem = new CheckItem();
chkItem.selected = i%3==0;
chkItem.setDisplayName("DisplayName" + i);
chkItem.setInternalName("InternalName" + i);
data.add(chkItem);
return data;
public static void main(String[] args)
launch(args);
检查项目
public class CheckItem
boolean selected;
String displayName;
String internalName;
public boolean isChecked()
return selected;
public void setChecked(boolean checked)
this.selected = checked;
public String getDisplayName()
return displayName;
public void setDisplayName(String displayName)
this.displayName = displayName;
public String getInternalName()
return internalName;
public void setInternalName(String internalName)
this.internalName = internalName;
【问题讨论】:
ComboBox
es 专门用于从项目列表中选择一个项目。我认为对于您想要的功能,我将从由CheckMenuItem
s 填充的MenuButton
开始。
ControlsFX 项目中还有一个CheckComboBox,您可能想看看。
感谢 José Pereda 不知何故我错过了这个!您可以将此添加为接受它的答案吗?谢谢!
【参考方案1】:
我的示例代码:
CheckedComboBox
类人
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()+")";
简单的包装器
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);
【讨论】:
【参考方案2】:如果您在实施中遇到问题,您应该查看ControlsFX 项目中的CheckComboBox 控件。
源码可以在here找到。
【讨论】:
嗨!如何将此 CheckComboBox 添加到 FXML 文件中? 请创建一个新问题。以上是关于带有复选框的 JavaFX 组合框的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 JavaFX 将选择框、复选框和文本字段实现为一个按钮 [关闭]