【问题标题】:JavaFX 8 MapProperty unbind does not work?JavaFX 8 MapProperty unbind 不起作用?
【发布时间】:2015-06-05 09:32:58
【问题描述】:

谁能解释一下这是一个错误还是我在 JavaFX MapProperty 绑定中遗漏了什么?

场景: 两个 MapProperty 实例 - 主实例和子实例。

  1. 首先我们将孩子绑定到主人
  2. 然后我们在master中存储一些值
  3. 将子节点与主节点解除绑定
  4. 清除孩子
  5. 两个实例都是空的 - 为什么?
  6. 在 child 中存储一些值
  7. 两个实例包含相同的值 - 为什么?

代码:

public static void main(String[] args) {

    MapProperty<String, Object> master = new SimpleMapProperty<String, Object>(
            FXCollections.observableMap(new HashMap<String, Object>()));
    MapProperty<String, Object> child = new SimpleMapProperty<String, Object>(
            FXCollections.observableMap(new HashMap<String, Object>()));

    child.bind(master);

    master.put("k1", "v1");

    System.out.println("Java version: " + System.getProperty("java.version"));
    System.out.println("OS version  : " + System.getProperty("os.name") + " - " + System.getProperty("os.arch"));
    System.out.println("------------");
    System.out.println("master: " + master);
    System.out.println("child : " + child);

    // Isn't this supposed to stop change listener ?????
    child.unbind();
    child.clear();

    System.out.println("------------");
    System.out.println("master: " + master);
    System.out.println("child : " + child);

    child.put("k2", "v2");

    System.out.println("------------");
    System.out.println("master: " + master);
    System.out.println("child : " + child);

}

输出:

run:
Java version: 1.8.0_45
OS version  : Windows 7 - amd64
------------
master: MapProperty [value: {k1=v1}]
child : MapProperty [bound, invalid]
------------
master: MapProperty [value: {}]
child : MapProperty [value: {}]
------------
master: MapProperty [value: {k2=v2}]
child : MapProperty [value: {k2=v2}]
BUILD SUCCESSFUL (total time: 0 seconds)

【问题讨论】:

    标签: java javafx-8 property-binding


    【解决方案1】:

    MapProperty 的值是 ObservableMap,而不是 ObservableMap 的内容。

    执行此代码

    MapProperty<String, Object> master = new SimpleMapProperty<String, Object>(
            FXCollections.observableMap(new HashMap<String, Object>()));
    MapProperty<String, Object> child = new SimpleMapProperty<String, Object>(
            FXCollections.observableMap(new HashMap<String, Object>()));
    
    ObservableMap<String, Object> childMap = child.get();
    ObservableMap<String, Object> masterMap = master.get();
    
    System.out.println("before binding: " + ((childMap == masterMap) ? "childMap == masterMap" : "childMap != masterMap"));
    
    child.bind(master);
    
    childMap = child.get();
    masterMap = master.get();
    
    System.out.println("after binding: " + ((childMap == masterMap) ? "childMap == masterMap" : "childMap != masterMap"));
    
    child.unbind();
    System.out.println("after unbinding: " + ((childMap == masterMap) ? "childMap == masterMap" : "childMap != masterMap"));   
    

    显示绑定后,childmain 中的 ObservableMap 是同一个对象,因为属性包裹的是地图而不是其内容:

    before binding: childMap != masterMap
    after binding: childMap == masterMap
    after unbinding: childMap == masterMap
    

    要绑定地图的内容,请改用bindContent。执行中

    MapProperty<String, Object> master = new SimpleMapProperty<String, Object>(
            FXCollections.observableMap(new HashMap<String, Object>()));
    MapProperty<String, Object> child = new SimpleMapProperty<String, Object>(
            FXCollections.observableMap(new HashMap<String, Object>()));
    
    child.bindContent(master);
    
    master.put("k1", "v1");
    
    System.out.println("Java version: " + System.getProperty("java.version"));
    System.out.println("OS version  : " + System.getProperty("os.name") + " - " + System.getProperty("os.arch"));
    System.out.println("------------");
    System.out.println("master: " + master);
    System.out.println("child : " + child);
    
    child.unbindContent(master);
    child.clear();
    
    System.out.println("------------");
    System.out.println("master: " + master);
    System.out.println("child : " + child);
    
    child.put("k2", "v2");
    
    System.out.println("------------");
    System.out.println("master: " + master);
    System.out.println("child : " + child);
    

    给出以下结果:

    Java version: 1.8.0_45
    OS version  : Windows 7 - amd64
    ------------
    master: MapProperty [value: {k1=v1}]
    child : MapProperty [value: {k1=v1}]
    ------------
    master: MapProperty [value: {k1=v1}]
    child : MapProperty [value: {}]
    ------------
    master: MapProperty [value: {k1=v1}]
    child : MapProperty [value: {k2=v2}]
    

    【讨论】:

    • 感谢您澄清这一点。我不明白 unbind() 方法。如果它不能提供预期的效果,那么拥有一个有什么意义呢?为简单起见,我的示例不太准确。我真正需要的是替换 master 而不是它的内容。内容绑定仍然有效,但如果新 master 包含与旧 master 相同的键和 null 作为某些值,您将有 NullPointerException。我会将您的答案标记为正确,因为它确实回答了我原来的问题。
    • 导致 NullPointerException 的行是这一行:'if (oldEntry == null ? newEntry != null : !newEntry.equals(oldEntry)) {' 在 MapExpressionHelper 类中。不应该是这样吗'if (oldEntry == null ? newEntry != null : !oldEntry.equals(newEntry)) {' ?
    • unbind() 方法为 MapProperty 的 ObservableMap 值提供了所需的效果。调用unbind()后,用master.set(map)设置ObservableMap对child没有影响,可以调用child.set(map)。我不确定我是否了解您在哪里得到 NullPointerException。也许最好用一个例子发布另一个问题。
    猜你喜欢
    • 1970-01-01
    • 2015-05-29
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 2019-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多