gpt4 book ai didi

java - 为自定义组合框创建监听器逻辑

转载 作者:行者123 更新时间:2023-12-02 09:33:33 25 4
gpt4 key购买 nike

我正在尝试为我创建的自定义组合框创建监听器逻辑,该组合框包含带有复选框的项目。

我无法继续,因为我不知道如何去做。

MainApplication.java

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);
}

}

ComboBoxItemWrap.java

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();
}

}

Person.java

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()+")";
}

}

在输出应用程序中,将填充带有复选框的项目列表。在列表中选择任意数量的条目时,条目名称将填充在组合框本身上,并以“;”分隔。现在我希望我的后端代码能够监听并识别已选择的条目,以便执行进一步的操作。

最佳答案

您可能不需要重新发明轮子。考虑使用ControlsFX CheckComboBox .

话虽这么说,代码中存在几个问题:

  1. 您永远不会更新 CheckBox 所选内容的属性。通过使用双向绑定(bind)可以轻松解决此问题。
  2. 由于 ComboBox 弹出窗口已关闭,因此在触发 MOUSE_RELEASED 事件时,CheckBox 不再处于启用状态。不过,这是 CheckBoxselected 状态发生变化的先决条件。修改皮肤可以让您改变这种行为。
  3. 您使用 ObservableList.filtered 创建 FilteredList,然后立即将其丢弃。您还可以在 MOUSE_RELEASED 事件过滤器中创建过滤列表的过滤列表。这本身并没有错,但是您在那里创建了一个昂贵的对象,而无需这样做:只需在那里获取一个流即可。如果结果只需要一次,那么这是一种更轻量级的过滤列表的方法。仅当您需要一个包含另一个 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() 的复选框添加 MOUSE_RELEASED 事件过滤器即可 而不是修改皮肤。

关于java - 为自定义组合框创建监听器逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57751633/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com