Java 为自定义组合框创建侦听器逻辑
我正在尝试为我创建的自定义组合框创建侦听器逻辑,该组合框包含带有复选框的项 我无法继续,因为我不知道如何做 MainApplication.javaJava 为自定义组合框创建侦听器逻辑,java,javafx,Java,Javafx,我正在尝试为我创建的自定义组合框创建侦听器逻辑,该组合框包含带有复选框的项 我无法继续,因为我不知道如何做 MainApplication.java public class MainApplication extends Application{ @Override public void start(Stage stage) { Scene scene = new Scene(new VBox(), 450, 250); ComboBox<
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", "12-Aug-1994")),
new ComboBoxItemWrap<>(new Person("B", "13-Aug-1994")),
new ComboBoxItemWrap<>(new Person("C", "14-Aug-1994"))
);
cb.setCellFactory( c -> {
ListCell<ComboBoxItemWrap<Person>> cell = new ListCell<ComboBoxItemWrap<Person>>(){
@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);
}
}
在输出应用程序中,将填充带有复选框的项目列表。在列表中选择任意数量的条目时,条目名称将填充在组合框本身上,并用“;”分隔。现在,我希望我的后端代码能够监听并识别已选择的条目,以便执行进一步的操作。您可能不需要重新发明控制盘。考虑使用.< /P> 尽管如此,代码中仍存在一些问题: 您永远不会在选中复选框时更新属性。这可以通过使用双向绑定轻松解决。 由于组合框弹出窗口已关闭,因此在触发鼠标释放事件时,复选框不再启用。这是复选框的选定状态的预请求站点。修改皮肤可以改变这种行为。 您可以使用ObservableList.filtered创建FilteredList,然后立即将其丢弃。您还可以在鼠标释放的事件筛选器中创建筛选列表的筛选列表。这本身并没有错,但您在那里创建了一个昂贵的对象,而不需要这样做:只需在那里获得一个流。如果结果只需要一次,这是一种更轻量级的列表过滤方法。仅当您需要包含另一个ObservableList中的元素并自动更新的ObservableList时,才使用filtered/FilteredList。 还请注意,有一种方法可以对属性的更改进行ObservableList触发器更新更改:使用observableArrayList方法,将提取器作为参数 这就是如何重写代码以使其正常工作:
VBox root = new VBox();
Scene scene = new Scene(root, 450, 250);
ComboBox<ComboBoxItemWrap<Person>> cb = new ComboBox<>();
ObservableList<ComboBoxItemWrap<Person>> options = FXCollections.observableArrayList(item -> new Observable[] {item.checkProperty()});
options.addAll(
new ComboBoxItemWrap<>(new Person("A", "12-Aug-1994")),
new ComboBoxItemWrap<>(new Person("B", "13-Aug-1994")),
new ComboBoxItemWrap<>(new Person("C", "14-Aug-1994")));
cb.setCellFactory(c -> new ListCell<ComboBoxItemWrap<Person>>() {
private final CheckBox cb = new CheckBox();
@Override
protected void updateItem(ComboBoxItemWrap<Person> item, boolean empty) {
ComboBoxItemWrap<Person> oldItem = getItem();
if (oldItem != null) {
// remove old binding
cb.selectedProperty().unbindBidirectional(oldItem.checkProperty());
}
super.updateItem(item, empty);
if (empty || item == null) {
setGraphic(null);
} else {
cb.selectedProperty().bindBidirectional(item.checkProperty());
cb.setText(item.toString());
setGraphic(cb);
}
}
});
// make sure popup remains open
ComboBoxListViewSkin<ComboBoxItemWrap<Person>> skin = new ComboBoxListViewSkin<>(cb);
skin.setHideOnClick(false);
cb.setSkin(skin);
cb.setItems(options);
cb.promptTextProperty().bind(Bindings.createStringBinding(() ->
options.stream().filter(ComboBoxItemWrap::getCheck).map(Object::toString).collect(Collectors.joining("; ")), options));
请注意,如果您想在取消选中复选框后关闭弹出窗口,只需为调用cb.arm的复选框添加鼠标释放的事件过滤器,而不是修改皮肤。谢谢您的回答,但我无法实现它。目前,setHideOnClick方法适用于ComboBoxListViewSkin类型,但在我的例子中,它是ComboBoxListViewSkin。我不确定如何处理这种类型不匹配。@AmitDRoy皮肤和组合框匹配的类型参数。因为我认为您的组合框不可能包含COMPBOX类型的项目,所以COBOBOXListVIEW应该与组合框一起使用。
public class Person {
private StringProperty name = new SimpleStringProperty();
private StringProperty birthday = new SimpleStringProperty();
public Person() {
}
public Person(String name, String 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 StringProperty getBirthdayProperty() {
return birthday;
}
public String getBirthdayValue() {
return birthday.getValue();
}
public void setBirthdayValue(String value) {
birthday.setValue(value);
}
@Override
public String toString() {
return getNameValue()+" ("+getBirthdayValue()+")";
}
}
VBox root = new VBox();
Scene scene = new Scene(root, 450, 250);
ComboBox<ComboBoxItemWrap<Person>> cb = new ComboBox<>();
ObservableList<ComboBoxItemWrap<Person>> options = FXCollections.observableArrayList(item -> new Observable[] {item.checkProperty()});
options.addAll(
new ComboBoxItemWrap<>(new Person("A", "12-Aug-1994")),
new ComboBoxItemWrap<>(new Person("B", "13-Aug-1994")),
new ComboBoxItemWrap<>(new Person("C", "14-Aug-1994")));
cb.setCellFactory(c -> new ListCell<ComboBoxItemWrap<Person>>() {
private final CheckBox cb = new CheckBox();
@Override
protected void updateItem(ComboBoxItemWrap<Person> item, boolean empty) {
ComboBoxItemWrap<Person> oldItem = getItem();
if (oldItem != null) {
// remove old binding
cb.selectedProperty().unbindBidirectional(oldItem.checkProperty());
}
super.updateItem(item, empty);
if (empty || item == null) {
setGraphic(null);
} else {
cb.selectedProperty().bindBidirectional(item.checkProperty());
cb.setText(item.toString());
setGraphic(cb);
}
}
});
// make sure popup remains open
ComboBoxListViewSkin<ComboBoxItemWrap<Person>> skin = new ComboBoxListViewSkin<>(cb);
skin.setHideOnClick(false);
cb.setSkin(skin);
cb.setItems(options);
cb.promptTextProperty().bind(Bindings.createStringBinding(() ->
options.stream().filter(ComboBoxItemWrap::getCheck).map(Object::toString).collect(Collectors.joining("; ")), options));