Это один из возможных способов сделать это, следуя своему подходу реализации AbstractPropertyEditor
с CheckComboBox
контролем.
Основываясь на HelloCheckComboBox
, я создал этот образец, используя класс Person
, фасоль Musicians
и собственный редактор.
Person
public static class Person {
private final StringProperty firstname = new SimpleStringProperty();
private final StringProperty lastname = new SimpleStringProperty();
private final ReadOnlyStringWrapper fullName = new ReadOnlyStringWrapper();
public Person(String firstname, String lastname) {
this.firstname.set(firstname);
this.lastname.set(lastname);
fullName.bind(Bindings.concat(firstname, " ", lastname));
}
public static final ObservableList<Person> createDemoList() {
final ObservableList<Person> result = FXCollections.observableArrayList();
result.add(new Person("Paul", "McCartney"));
result.add(new Person("Andrew Lloyd", "Webber"));
result.add(new Person("Herb", "Alpert"));
result.add(new Person("Emilio", "Estefan"));
result.add(new Person("Bernie", "Taupin"));
result.add(new Person("Elton", "John"));
result.add(new Person("Mick", "Jagger"));
result.add(new Person("Keith", "Richerds"));
return result;
}
public final StringProperty firstnameProperty() {
return this.firstname;
}
public final java.lang.String getFirstname() {
return this.firstnameProperty().get();
}
public final void setFirstname(final String firstname) {
this.firstnameProperty().set(firstname);
}
public final StringProperty lastnameProperty() {
return this.lastname;
}
public final String getLastname() {
return this.lastnameProperty().get();
}
public final void setLastname(final String lastname) {
this.lastnameProperty().set(lastname);
}
public final ReadOnlyStringProperty fullNameProperty() {
return this.fullName.getReadOnlyProperty();
}
public final String getFullName() {
return this.fullNameProperty().get();
}
@Override
public String toString() {
return getFullName();
}
@Override
public int hashCode() {
int hash = 3;
hash = 79 * hash + Objects.hashCode(this.firstname);
hash = 79 * hash + Objects.hashCode(this.lastname);
hash = 79 * hash + Objects.hashCode(this.fullName);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Person other = (Person) obj;
if (!Objects.equals(getFirstname(), other.getFirstname())) {
return false;
}
if (!Objects.equals(getLastname(), other.getLastname())) {
return false;
}
return Objects.equals(this.getFullName(), other.getFullName());
}
}
Музыканты
Этот класс содержит StringProperty
поля, которое будет редактироваться с TextField
, и ListProperty<Person>
поля, которое будет отредактировано CheckComboBox<Person>
управления:
public static class Musicians {
private final StringProperty category = new SimpleStringProperty();
private final ListProperty<Person> persons = new SimpleListProperty<>(FXCollections.observableArrayList());
public Musicians() { }
public String getCategory() {
return category.get();
}
public void setCategory(String category) {
this.category.set(category);
}
public StringProperty categoryProperty() {
return category;
}
public void setPersons(ObservableList<Person> value) {
this.persons.set(value);
}
public ObservableList<Person> getPersons() {
return persons.get();
}
public ListProperty<Person> personsProperty() {
return persons;
}
}
CustomPropertyEditorFactory
Теперь мы предоставляем наши собственные PropertyEditorFactory
, используя тот же текстовый редактор как DefaultEditorFactory
для полей Струнных и добавления CheckComboBox
реализации.
Заметим, что мы должны заполнить список предметов CheckComboBox
, и в этом случае это будет сделано с Person.createDemoList()
.
public class CustomPropertyEditorFactory implements Callback<Item, PropertyEditor<?>> {
@Override public PropertyEditor<?> call(Item item) {
Class<?> type = item.getType();
if (type == String.class) {
return createTextEditor(item);
}
if (type != null && type == javafx.collections.ObservableList.class) {
return createCheckComboBoxEditor(item, Person.createDemoList());
}
return null;
}
public final PropertyEditor<?> createTextEditor(PropertySheet.Item property) {
return new AbstractPropertyEditor<String, TextField>(property, new TextField()) {
@Override protected StringProperty getObservableValue() {
return getEditor().textProperty();
}
@Override public void setValue(String value) {
getEditor().setText(value);
}
};
}
public final <T> PropertyEditor<?> createCheckComboBoxEditor(PropertySheet.Item property, final Collection<T> choices) {
return new AbstractPropertyEditor<ObservableList<T>, CheckComboBox<T>>(property, new CheckComboBox<>()) {
private ListProperty<T> list;
{
getEditor().getItems().setAll(choices);
}
@Override
protected ListProperty<T> getObservableValue() {
if (list == null) {
list = new SimpleListProperty<>(getEditor().getCheckModel().getCheckedItems());
}
return list;
}
@Override
public void setValue(ObservableList<T> checked) {
checked.forEach(getEditor().getCheckModel()::check);
}
};
}
}
Наконец, мы можем использовать этот обычай завода в нашем приложении:
@Override
public void start(Stage primaryStage) {
PropertySheet propertySheet = new PropertySheet();
propertySheet.setPropertyEditorFactory(new CustomPropertyEditorFactory());
Musicians address = new Musicians();
// 1: set initial selected values:
address.getPersons().add(new Person("Paul", "McCartney"));
// 2: listen to changes in selection:
address.personsProperty().addListener((ors, ov, nv) -> {
System.out.println("Selected persons:");
nv.forEach(System.out::println);
});
propertySheet.getItems().setAll(BeanPropertyUtils.getProperties(address));
Scene scene = new Scene(propertySheet, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}