【问题标题】:JavaFX ObservableList Concrete ImplementationJavaFX ObservableList 具体实现
【发布时间】:2016-05-18 22:14:21
【问题描述】:

我有使用 JAXB 从 XSD 生成的类。 JAXB 自定义绑定的选项之一是指定 java.util.List 实现类。例如,我可以指定 JAXB 使用 java.util.LinkedList 类,生成的代码将包括以下内容:

if (myList == null)
    myList = new java.util.LinkedList();

我希望实现返回javafx.collections.ObservableList,但找不到任何实现该接口并具有默认构造函数的具体类。有谁知道带有默认构造函数的javafx.collections.ObservableList 的具体实现?

【问题讨论】:

  • 你试过 FXCollections.observableArrayList();它创建一个由 arraylist 支持的新的空 observable 列表。
  • 问题是我没有写代码……它是由 JAXB 生成的。我只能告诉代码要实例化的类型,并且该类型必须提供默认构造函数。
  • 你能自己做吗?扩展您找到的现有构造函数之一,并在新类中提供默认构造函数。

标签: java javafx jaxb javafx-8


【解决方案1】:

这个静态函数将为您提供 ObservableList 的具体实现: FXCollections.observableArrayList()

【讨论】:

    【解决方案2】:

    好的,有两种方法可以做到这一点。首先是实现自己的javafx.utils.ObservableListModifiableObservableListBase 的文档中提供了以下实现(稍作修改):

    public class ObservableArrayList<T> extends ModifiableObservableListBase<T> {
        private final List<E> delegate = new ArrayList<>();
    
        @Override
        public E get(final int index) {
            return delegate.get(index);
        }
    
        @Override
        public int size() {
            return delegate.size();
        }
    
        @Override
        protected void doAdd(final int index, final E element) {
            delegate.add(index, element);
        }
    
        @Override
        protected E doSet(final int index, final E element) {
            return delegate.set(index, element);
        }
    
        @Override
        protected E doRemove(final int index) {
            return delegate.remove(index);
        }
    }
    

    然后,JAXB 可以将此类用作实现列表类型,方法是将以下内容添加到绑定文件中:

    <bindings node="//xsd:element[@name='Item']">
      <property name="Items" collectionType="myNamespace.ObservableArrayList">
        <baseType name="myNamespace.Item" />
      </property>
    </bindings>
    

    第二个选项,也是我决定使用的选项,是将 JAXB 编组器/解组器配置为使用从生成的类继承的自定义实现类。假设 XSD 定义了一个名为“ItemCollectionType”的复杂类型,其中包含一个名为“Item”的元素定义和无限的maxOccurs。然后我只需将以下内容添加到 JAXB 绑定文件中:

    <bindings node="./xsd:complexType[@name='ItemCollectionType']">
      <class implClass="myNamespace.ItemCollection" />
    </bindings>
    
    <bindings node="//xsd:element[@name='Item']">
      <property name="Items">
        <baseType name="myNamespace.Item" />
      </property>
    </bindings>
    

    上面强制在生成的代码中每次出现ItemCollectionType 都用myNamespace.ItemCollection 类型替换。然后,ItemCollectionType 的生成实现包括以下代码:

    @XmlElement(name = "Item", required = true, type = myNamespace.Item.class)
    protected List<myNamespace.Item> items;
    
    public List<myNamespace.Item> getItems() {
        if (items == null) {
            items = new ArrayList<myNamespace.Item>();
        }
        return this.items;
    }
    

    然后,我在myNamespace.ItemCollection 中重写了这个方法:

    @Override
    public ObservableList<Item> getItems() {
        if (!(super.getItems() instanceof ObservableList)) {
            items = FXCollections.observableList(items);
        }
        return (ObservableList<Item>)items;
    }
    

    当然,这两个选项并不相互排斥。我可以很容易地实现它们,这会将myNamespace.ItemCollection.getItems 的实现简化为一个简单的转换。

    【讨论】:

    • 您的实现类似于ObservableListWrapper
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    • 1970-01-01
    • 1970-01-01
    • 2017-04-30
    • 2013-11-25
    • 2014-04-07
    • 1970-01-01
    相关资源
    最近更新 更多