2016-03-27 3 views
2

Я хочу добавить CheckComboBox в PropertySheet в libraryfx-библиотеке. Редактор по умолчанию содержит только реализацию ComboBox. Можно ли добавить CheckComboBox? Я попытался реализовать PropertyEditor с AbstractPropertyEditor, но получаю исключение.Добавить CheckComboBox в PropertySheet JavaFX

public static final <T> PropertyEditor<?> createCheckComboBoxEditor(PropertySheet.Item property, 
     final Collection<T> choices) { 
    final ObservableList<T> result = FXCollections.observableArrayList(); 
    result.addAll(choices); 
    CheckComboBox<T> comboBox = new CheckComboBox<T>(result); 
    return new AbstractPropertyEditor<ObservableList<T>, CheckComboBox<T>>(property, comboBox) { 

     { 
      getEditor().getCheckModel().getCheckedItems().setAll(FXCollections.observableArrayList(choices));     
     } 
     @Override 
     public void setValue(ObservableList<T> value) { 
      getEditor().getCheckModel().getCheckedItems().setAll(value); 
     } 

     @Override 
     protected ObservableValue<ObservableList<T>> getObservableValue() { 
      return (ObservableValue<ObservableList<T>>) getEditor().getItems(); 
     } 
    }; 
} 

Исключение:

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: com.sun.javafx.collections.ObservableListWrapper cannot be cast to javafx.beans.value.ObservableValue 
at configurator.ComboBoxEditor$3.getObservableValue(ComboBoxEditor.java:109) 
at org.controlsfx.property.editor.AbstractPropertyEditor.<init>(AbstractPropertyEditor.java:83) 
at org.controlsfx.property.editor.AbstractPropertyEditor.<init>(AbstractPropertyEditor.java:67) 
at configurator.ComboBoxEditor$3.<init>(ComboBoxEditor.java:85) 
at configurator.ComboBoxEditor.createCheckComboBoxEditor(ComboBoxEditor.java:85) 
at configurator.ConfiguratorController.lambda$setPropertySheetEditors$7(ConfiguratorController.java:273) 
at impl.org.controlsfx.skin.PropertySheetSkin$PropertyPane.getEditor(PropertySheetSkin.java:321) 
at impl.org.controlsfx.skin.PropertySheetSkin$PropertyPane.setItems(PropertySheetSkin.java:301) 
at impl.org.controlsfx.skin.PropertySheetSkin$PropertyPane.<init>(PropertySheetSkin.java:269) 
at impl.org.controlsfx.skin.PropertySheetSkin$PropertyPane.<init>(PropertySheetSkin.java:261) 
at impl.org.controlsfx.skin.PropertySheetSkin.buildPropertySheetContainer(PropertySheetSkin.java:223) 
at impl.org.controlsfx.skin.PropertySheetSkin.refreshProperties(PropertySheetSkin.java:188) 
at impl.org.controlsfx.skin.PropertySheetSkin.lambda$new$65(PropertySheetSkin.java:140) 

ответ

1

Это один из возможных способов сделать это, следуя своему подходу реализации 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(); 
} 

checkcombobox

Смежные вопросы