0.前言
- PropertySheet 是一个垂直的属性列表,通常用来显示并编辑一个对象的各种属性。
-
支持字符串、数字、布尔值、枚举、颜色和字体编辑器。除了支持内置编辑器,还可以自定义编辑器。
[PropertySheet ]
- PropertySheet 是一个控件,可以放置于各种pane内。
1.PropertySheet的简单使用
- 如下代码创建一个PropertySheet,显示一个Mission对象的各种属性,让终端用户修改。
- 如果没有特殊要求,如下代码可以很简洁的完成对象的属性编辑gui创建。
- 但是,通常都有特殊要求的。比如属性的显示名称,属性分类的定义。编辑器的自定义等。
PropertySheet propertySheet = new PropertySheet(BeanPropertyUtils.getProperties(new Mission()));
rootLayoutBorderPane.setCenter(propertySheet);
2.PropertySheet使用代码的详细解释
- 这段话,是看了PropertySheet的源代码,自己书写的。网上相关的资料实在太少了。
- PropertySheet类的构造函数,接收一个PropertySheet.Item对象列表。
- PropertySheet.Item是一个接口,定义如下:
- 可以自己实现PropertySheet.Item。每个 Item 代表一个可由最终用户编辑的单个属性。
- 就是说,不仅仅是一个对象的属性可以由PropertySheet来展示并编辑,任何属性列表都可以。如下展示了一个PropertySheet.Item的范例。用来修改一个map。
- BeanProperty类。这个类实现PropertySheet.Item接口。接收一个bean对象,以及一个bean对象属性描述对象,通过反射,来实现对象属性的修改。通常使用的是这个对象。
- BeanPropertyUtils类。这个类主要是一个工具类,对一个bean的各种属性,创建一个BeanProperty类的列表。
public static interface Item {
public Class<?> getType();
public String getCategory();
public String getName();
public String getDescription();
public Object getValue();
public void setValue(Object value);
public Optional<ObservableValue<? extends Object>>
default public Optional<Class<? extends PropertyEditor<?>>> getPropertyEditorClass() {
return Optional.empty();
}
default public boolean isEditable() {
return true;
}
}
private static Map<String, Object> customDataMap = new LinkedHashMap<>();
static {
customDataMap.put("Group 1#My Text", "Same text"); // Creates a TextField in property sheet
customDataMap.put("Group 1#My Date", LocalDate.of(2000, Month.JANUARY, 1)); // Creates a DatePicker
customDataMap.put("Group 2#My Enum Choice", SomeEnumType.EnumValue); // Creates a ChoiceBox
customDataMap.put("Group 2#My Boolean", false); // Creates a CheckBox
customDataMap.put("Group 2#My Number", 500); // Creates a NumericField
}
class CustomPropertyItem implements PropertySheet.Item {
private String key;
private String category, name;
public CustomPropertyItem(String key) {
this.key = key;
String[] skey = key.split("#");
category = skey[0];
name = skey[1];
}
@Override
public Class<?> getType() {
return customDataMap.get(key).getClass();
}
@Override
public String getCategory() {
return category;
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return null;
}
@Override
public Object getValue() {
return customDataMap.get(key);
}
@Override
public void setValue(Object value) {
customDataMap.put(key, value);
}
}
public PropertySheetExample {
ObservableList<PropertySheet.Item> list = FXCollections.observableArrayList();
for (String key : customDataMap.keySet())
list.add(new CustomPropertyItem(key));
PropertySheet propertySheet = new PropertySheet(list);
VBox.setVgrow(propertySheet, Priority.ALWAYS);
getChildren().add(propertySheet);
}
}
3. PropertySheet自定义编辑器
3.1 编辑器接口
public interface PropertyEditor<T> {
public Node getEditor();
public T getValue();
public void setValue(T value);
}
3.2 AbstractPropertyEditor<T, C extends Node> implements PropertyEditor<T>编辑器
- 这个主要是利用javafx的各种控件来实现控制器
3.3 Editors类和DefaultPropertyEditorFactory类
- 这个是策略模式,Editors类用来返回各种编辑器(都是 AbstractPropertyEditor类)。
- DefaultPropertyEditorFactory类,通过各种策略(传入的item)来访问Editors类获得各种编辑器。
- DefaultPropertyEditorFactory类先判断item的getPropertyEditorClass是否为null,如果不为null就通过这个class的构造函数来创建一个编辑器。如果为空,就通过item的属性类型(字符串,数字,或逻辑值)来创建编辑器。
4. 自定义编辑器
- 综上,自定义编辑器有2种方法。第一种,自定义 DefaultPropertyEditorFactory类。这个有点麻烦。。。第二种覆盖item的getPropertyEditorClass默认接口方法。如果是用BeanProperty,就需要覆盖BeanProperty的getPropertyEditorClass默认接口方法
- 通过第二种方法创建的编辑器,必须有一个接收item的构造函数。
5. 自定义编辑器的例子
- 第1步,实现一个editor类
public class NumberSliderEditor extends AbstractPropertyEditor<String, TextArea> {
public NumberSliderEditor(PropertySheet.Item property, TextArea control) {
super(property, control);
}
public NumberSliderEditor(PropertySheet.Item property) {
super(property, new TextArea());
}
@Override
protected ObservableValue<String> getObservableValue() {
return getEditor().textProperty();
}
@Override
public void setValue(String value) {
getEditor().setText(value);
}
}
- 第2步,继承BeanProperty并覆盖方法
public Optional<Class<? extends PropertyEditor<?>>> getPropertyEditorClass() {
return Optional.of(NumberSliderEditor.class);
}
参考文章
1.javafx – 使用PropertyEditor(ControlsFX)的属性表示例
2.Property sheet example with use of a PropertyEditor (ControlsFX)
3.
网友评论