我已经搜索了很多关于ControlsFX PropertySheet用法的好例子,但是除了这个我什么也找不到。
在本例中,包含NameItem对象的ObservableList项被添加到PropertySheet对象的构造函数中,正如文档所述。
http://controlsfx.bitbucket.org/org/controlsfx/control/PropertySheet.html
但是,正如本文档所述,PropertySheet的列“提供了一个允许最终用户操作该属性的PropertyEditor”。它甚至说,在编辑器包中提供的许多编辑器中,有一个“CheckEditor、ChoiceEditor、TextEditor和FontEditor”。
我不想局限于我的NameItem示例。我还想添加复选框、选择框和其他动态编辑器元素。谁能举例说明如何使用一个或多个编辑器来构建一个简单的PropertySheet?
发布于 2014-09-26 20:59:58
根据属性类型的不同,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);
}
}可以通过两种方式进一步扩展此行为。首先,现有的编辑器可以用于默认属性编辑器工厂不支持的类型。下面的示例设置新的属性编辑器工厂,该工厂将为List类型创建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);
}
});最后,我们可以创建自定义编辑器并覆盖PropertySheet.Item中的getPropertyEditorClass()方法,以返回自定义编辑器类型。在这种情况下,默认的属性编辑器工厂将创建编辑器,不需要覆盖工厂方法。
发布于 2014-09-17 23:19:16
即使在看了示例并试图找到更多信息后,我也非常困惑如何在属性表中更改用户输入的类型。我花了一段时间才弄明白,但事实证明答案相对简单。
关键是PropertyEditorFactory,它可以使用setPropertyEditorFactory(Callback<PropertySheet.Item,PropertyEditor<?>> factory)直接设置到PropertySheet上。在这个回调中,该方法返回一个包含在编辑器包中的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);
}
}
});然而,一旦你覆盖了这个编辑器工厂,你必须为你需要的每种类型的设置提供一个PropertyEditor,例如,如果你只返回Editors.createNumericEditor(param);,但是有字符串选项,你会得到一个异常。另外,不要覆盖PropertySheet.Item中的getPropertyEditorClass(),这是我浪费了大部分时间的地方。希望这篇文章能对任何想要这样做的人有所帮助!
发布于 2016-08-04 19:08:36
我找不到任何用于PropertySheet的自定义Editor的示例,但我想我现在已经弄明白了。在我的例子中,我只是想使用Slider作为Number的编辑器。这可能不切实际,因为您无法看到Slider的价值,但我认为Slider可以简单地替换为一个带有滑块和标签的窗格。
首先,我们需要我们的Item实现,这里是controlsfx-samples的一个稍微修改过的版本。Map被移到这个类中,但可以在任何地方。不过,您可能根本不想使用映射,因为将类别和名称组合在一起已经有点不切实际;此外,还没有为项目创建描述的空间。
public class CustomPropertyItem implements PropertySheet.Item {
public static Map<String, Object> customDataMap = new LinkedHashMap<>();
static {
customDataMap.put("basic.My Text", "Same text"); // Creates a TextField in property sheet
customDataMap.put("basic.My Date", LocalDate.of(2016, Month.JANUARY, 1)); // Creates a DatePicker
customDataMap.put("misc.My Enum", SomeEnum.ALPHA); // Creates a ChoiceBox
customDataMap.put("misc.My Boolean", false); // Creates a CheckBox
customDataMap.put("misc.My Number", 500); // Creates a NumericField
customDataMap.put("misc.My Color", Color.ALICEBLUE); // Creates a ColorPicker
}
private String key;
private String category, name;
public CustomPropertyItem(String key)
{
this.key = key;
String[] skey = key.split("\\.", 2);
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() {
// doesn't really fit into the map
return null;
}
@Override
public Object getValue() {
return customDataMap.get(key);
}
@Override
public void setValue(Object value) {
customDataMap.put(key, value);
}
@Override
public Optional<ObservableValue<? extends Object>> getObservableValue() {
return Optional.empty();
}
@Override
public Optional<Class<? extends PropertyEditor<?>>> getPropertyEditorClass() {
// for an item of type number, specify the type of editor to use
if (Number.class.isAssignableFrom(getType())) return Optional.of(NumberSliderEditor.class);
// ... return other editors for other types
return Optional.empty();
}
}接下来是PropertyEditor实现,它是一个Node和一组将属性项值与控件连接起来的方法。第一个构造函数是实现所必需的,是第二个构造函数,因为Editors.createCustomEditor(Item)方法使用反射来查找此构造函数。您不必使用此方法,但默认的PropertyEditorFactory很可能依赖于此。如果您出于某种原因想要避免反射,则不需要在Item中覆盖getPropertyEditorClass(),您可以使用setPropertyEditorFactory(Callback)并在其中创建PropertyEditor的新实例。请注意,您根本不需要使用setPropertyEditorFactory(Callback) (在本例中)。
public class NumberSliderEditor extends AbstractPropertyEditor<Number, Slider> {
public NumberSliderEditor(Item property, Slider control)
{
super(property, control);
}
public NumberSliderEditor(Item item)
{
this(item, new Slider());
}
@Override
public void setValue(Number n) {
this.getEditor().setValue(n.doubleValue());
}
@Override
protected ObservableValue<Number> getObservableValue() {
return this.getEditor().valueProperty();
}
}从这里开始,您只需创建PropertySheet并添加所有映射条目。
PropertySheet propertySheet = new PropertySheet();
for (String key : CustomPropertyItem.customDataMap.keySet()) propertySheet.getItems().add(new CustomPropertyItem(key));我希望这对任何人都有帮助,因为似乎没有任何示例显示自定义Editor的用法。唯一的提示是Item.getPropertyEditorClass()的javadoc,它有一个默认的接口实现,所以你通常不会去看它。事实上,这里的答案是不要查看这个方法,这也没有帮助:/
https://stackoverflow.com/questions/24238858
复制相似问题