首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将JavaFx属性绑定到多个可观察到的

将JavaFx属性绑定到多个可观察到的
EN

Stack Overflow用户
提问于 2017-02-22 16:19:14
回答 1查看 1.3K关注 0票数 0

我正在编写一个JavaFx控件,该控件由一个获取用户输入的子控件(例如TextField )组成。主组件拥有一个属性,该属性表示文本的解析表示,例如LocalDateTime。当用户输入某项内容时,应该更新该属性,因此我将其绑定到子属性的value属性。还应该可以通过绑定value属性从外部更改当前值,因此必须是双向绑定才能自动更新子节点。控件可以正常工作,直到客户端代码绑定到属性为止。下面的代码显示了我的问题:

进口javafx.beans.property.SimpleIntegerProperty;

代码语言:javascript
复制
public class Playbook {

    // The internal control with a property p
    static class Child {
        public SimpleIntegerProperty p = new SimpleIntegerProperty();

        public void set(int i) {p.set(i);}
    }

    // My new control with a property value which is bound
    // bidirectionally to Child.p
    static class Parent {
        public Child a1;

        public SimpleIntegerProperty value = new SimpleIntegerProperty();

        public Parent() {
            a1 = new Child();

            value.bindBidirectional(a1.p);
        }
    }

    public static void main(String[] args) {
        Parent p = new Parent();

        // some client code wants to keep the 
        // value updated and thus binds to it
        SimpleIntegerProperty outside = new SimpleIntegerProperty();
        p.value.bind(outside);

        // simulate a change in the child control
        p.a1.p.set(10);         
    }
}

当我运行代码时,我会得到一个异常,即不能设置绑定属性:

代码语言:javascript
复制
Caused by: java.lang.RuntimeException: A bound value cannot be set.
    at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:143)
    at com.sun.javafx.binding.BidirectionalBinding$BidirectionalIntegerBinding.changed(BidirectionalBinding.java:467)

我相信这一定是一个常见的问题,我只是看不到明显的解决办法。我正在使用ReactFx,因此欢迎使用普通JavaFx或ReactFx的任何解决方案。真正的代码使用Var.mapBidirectional在内部绑定父属性和子属性。

我想要实现的是: 1.如果outside的值发生变化,则应将其传播到p.value,然后传播到p.a1.p2。如果p.a1.p更改,则应将其传播到p.value。

由此,我得出结论,Parent.value和Parent.a1.p总是完全相同的(加上在映射中应用的一些转换),而这是一个缩略图。外部可以独立变化,并且可以与值不同,所以我使用单向绑定。

EN

回答 1

Stack Overflow用户

发布于 2017-02-23 14:16:11

在理解了JavaFx绑定并不像我想象的那样,并且语义不允许这样做之后,我转向了反应‘s’s EventStream/Val/Var。ReactFx的模型似乎更符合我的预期,它允许我创建一个系统,其行为如下:

  1. 如果外部值发生变化,则应将其传播到p.value,然后传播到p.a1.p。
  2. 如果p.a1.p更改,则应将其传播到p.value

下面的代码实现了这一点。它使用了两个Var,它们是通过投标方式绑定的,因此其中一个的更改被提供给另一个Var。来自外部的更改被定义为一个EventStream,它被馈送给Var之一。

代码语言:javascript
复制
import org.reactfx.EventStream;
import org.reactfx.EventStreams;
import org.reactfx.value.Var;

import javafx.beans.property.SimpleIntegerProperty;

public class Playbook {

    static class Child {
        public Var<Integer> p = Var.newSimpleVar(0);

        public void set(int i) {this.p.setValue(i);}
    }

    static class Parent {
        public Child a1;

        public Var<Integer> value = Var.newSimpleVar(0);

        public Parent() {
            this.a1 = new Child();

            this.value.bindBidirectional(this.a1.p);
        }
    }

    public static void main(String[] args) {
        Parent p = new Parent();

        // some client code wants to keep the
        // value updated and thus binds to it
        SimpleIntegerProperty outside = new SimpleIntegerProperty();

        // A SimpleIntegerProperty is not a Property<Integer> but a 
        // Property<Number> so we have to use map to translate to Integer
        EventStream<Integer> stream = EventStreams.valuesOf(outside).map(Number::intValue);

        stream.feedTo(p.value);

        // simulate a change in the child control
        p.a1.p.setValue(10);
        System.out.println( p.value.getValue() );
        System.out.println(p.a1.p.getValue() );
        System.out.println(outside.get());

        // feed new value from outside
        outside.set(42);

        System.out.println( p.value.getValue() );
        System.out.println(p.a1.p.getValue() );
        System.out.println(outside.get());
    }
}

程序运行并打印

代码语言:javascript
复制
10
10
0
42
42
42
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42396873

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档