2014-06-16 65 views
3

我一直在寻找很多使用ControlsFX PropertySheet的好例子,但找不到任何东西。使用属性编辑器(ControlsFX)的属性表示例

https://www.google.nl/search?q=Main.java+amazonaws.com&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:nl:official&client=firefox-a&channel=sb&gfe_rd=cr&ei=d5aeU5bvBI3k-gan94HQBA#channel=sb&q=https%3A%2F%2Fbitbucket-assetroot.s3.amazonaws.com%2Fcontrolsfx%2Fcontrolsfx+Main.java&rls=org.mozilla:nl:official

在这个例子中,其包括命名选项对象ObservableList物品,被添加到的PropertySheet对象在其构造就像文档讲述。

http://controlsfx.bitbucket.org/org/controlsfx/control/PropertySheet.html

然而,如本文档中说,一个的PropertySheet的列“提供了属性编辑允许最终用户操纵该属性的装置”。它甚至说在Editors软件包中有许多编辑器中有一个“CheckEditor,ChoiceEditor,TextEditor和FontEditor”。

我不想仅限于我的NameItem示例。我也想添加复选框,选择框和其他动态编辑器元素。任何人都可以请举例说明如何使用一个或多个编辑器来构建一个简单的PropertySheet?

+0

你看过样品吗?具体的HelloPropertySheet示例。 –

回答

2

即使在查看示例并试图了解更多信息之后,我也很困惑如何更改属性表中的用户输入类型。我花了一段时间才弄明白,但结果却是相对简单。

关键是PropertyEditorFactory,它可以使用setPropertyEditorFactory(Callback<PropertySheet.Item,PropertyEditor<?>> factory)直接设置到PropertySheet中。在此回调中,此方法返回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); 
     } 
    } 
}); 

但是一旦你重写此编辑器的工厂,你必须为每个类型设置你所需要的,例如一个属性编辑器,如果你只返回Editors.createNumericEditor(param);但不得不字符串选项,你会得到一个异常。也不要重写PropertySheet.Item中的getPropertyEditorClass(),这是我浪费大部分时间的地方。希望这有助于任何尝试这样做的人!

4

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); 
    } 
} 

此行为可以通过两种方式进一步扩展。首先,现有的编辑器可用于默认属性编辑器工厂不支持的类型。以下示例将设置新的属性编辑器工厂,该工厂将为列表<字符串>类型创建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.ItemgetPropertyEditorClass()方法返回的自定义编辑器类型。在这种情况下,默认属性编辑器工厂将创建编辑器,并且不需要覆盖工厂方法。

1

我找不到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最可能依赖于此。 如果你想避免由于某种原因反思,你不需要覆盖getPropertyEditorClass()你的Item,你可以使用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,它有一个默认的接口实现,所以你通常不会看它。事实上,在这里有一个答案,说不看这种方法也没有帮助:/