我一直在搜索使用ControlsFX PropertySheet的任何好例子,但除了这个之外找不到任何东西.
在此示例中,包含NameItem对象的ObservableList项在其构造函数中添加到PropertySheet对象,就像文档所述.
http://controlsfx.bitbucket.org/org/controlsfx/control/PropertySheet.html
但是,正如本文档所述,PropertySheet的一列"提供了一个PropertyEditor,允许最终用户操纵该属性".它甚至说在编辑器包中提供了许多编辑器中的"CheckEditor,ChoiceEditor,TextEditor和FontEditor".
我不想仅限于我的NameItem示例.我还想添加复选框,选择框和其他动态编辑器元素.任何人都可以举例说明如何使用一个或多个编辑器来构建一个简单的PropertySheet吗?
小智 8
PropertySheet确实支持很少的属性编辑器,具体取决于属性类型.
以下示例是ControlsFX示例应用程序的扩展.它显示了String,LocalDate,Enum,Boolean和Integer类型如何分别映射到TextField,DatePicker,ChoiceBox,CheckBox和NumericField.
public class PropertySheetExample extends VBox {
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这种行为可以通过两种方式进一步扩展.首先,现有编辑器可用于默认属性编辑器工厂不支持的类型.下面的示例设置新的属性编辑器工厂,它将为List <String>类型创建ChoiceBox.对于其他类型,它将编辑器创建委派给默认工厂.
SimpleObjectProperty<Callback<PropertySheet.Item, PropertyEditor<?>>> propertyEditorFactory = new SimpleObjectProperty<>(this, "propertyEditor", new DefaultPropertyEditorFactory());
propertySheet.setPropertyEditorFactory(new Callback<PropertySheet.Item, PropertyEditor<?>>() {
@Override
public PropertyEditor<?> call(PropertySheet.Item param) {
if(param.getValue() instanceof List) {
return Editors.createChoiceEditor(param, (List) param.getValue());
}
return propertyEditorFactory.get().call(param);
}
});
Run Code Online (Sandbox Code Playgroud)
最后,我们可以getPropertyEditorClass()从PropertySheet.Item创建自定义编辑器和覆盖方法,以返回自定义编辑器类型.在这种情况下,默认属性编辑器工厂将创建编辑器,并且不需要覆盖工厂方法.
小智 3
即使在查看了示例并试图了解更多信息之后,我也对如何更改属性表中用户输入的类型感到非常困惑。我花了大约一段时间才弄清楚,但事实证明答案相对简单。
关键是 PropertyEditorFactory,它可以使用直接设置到 PropertySheet 上。setPropertyEditorFactory(Callback<PropertySheet.Item,PropertyEditor<?>> factory)在此回调中,该方法返回包含在 Editors 包中的 PropertyEditor 类型。由于调用提供了 PropertySheet.Item 参数,因此您可以检索正在设置的值,在下面的示例中,我检查了返回对象的类型以提供相关的编辑器。
propertySheet.setPropertyEditorFactory(new Callback<PropertySheet.Item, PropertyEditor<?>>() {
@Override
public PropertyEditor<?> call(Item param) {
if(param.getValue() instanceof String[]) {
return Editors.createChoiceEditor(param, choices);
} else if (param.getValue() instanceof Boolean) {
return Editors.createCheckEditor(param);
} else if (param.getValue() instanceof Integer) {
return Editors.createNumericEditor(param);
} else {
return Editors.createTextEditor(param);
}
}
});
Run Code Online (Sandbox Code Playgroud)
然而,一旦您覆盖此编辑器工厂,您必须为您需要的每种类型的设置提供一个 PropertyEditor,例如,如果您只返回Editors.createNumericEditor(param);但有 String 选项,您将得到一个异常。也不要覆盖 PropertySheet.Item 中的 getPropertyEditorClass() ,这是我浪费了大部分时间的地方。希望这可以帮助其他尝试这样做的人!