JavaFX实现链接属性

时间:2015-02-02 08:58:50

标签: javafx javafx-8

在JavaFX中实现链接或相互依赖属性的最佳方法是什么?

例如,我有一个区间,我希望通过三个整数属性lowerupperrange表示range = upper - lower,如果你尝试设置它也设置为上限的范围(到lower + range)。

这在传统Java Bean(set / get方法)中很简单,但JavaFX属性包括Observable概念和Bindings,它似乎很快变得复杂。

我尝试过绑定但这会使目标属性无法设置,也会出现双向绑定,但我只能绑定“等式”,而不是表达式。

我已经开始将range作为javafx.beans.property.IntegerProperty实施,但处理听众等似乎需要做很多工作。

有更简单的方法吗?

编辑: 这就是使用JavaBean模式的原因:

private int lower = 0;
private int upper = 0;

public int getLower() {
    return lower;
}
public void setLower(int lower) {
    this.lower = lower;
}

public int getUpper() {
    return upper;
}
public void setUpper(int upper) {
    this.upper = upper;
}

public int getRange() {
    return upper - lower;
}
public void setRange(int range) {
    upper = lower + range;
}

我将如何以JavaFX方式执行此操作? 这是我尝试的内容

IntegerProperty lower = new SimpleIntegerProperty(this, "lower", 0);
IntegerProperty upper = new SimpleIntegerProperty(this, "upper", 0);
IntegerProperty range = new SimpleIntegerProperty(this, "range", 0);

public LinkedPropTest() { // Constructor
    lower.addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
        range.setValue(upper.getValue() - lower.getValue());
    });
    upper.addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
        range.setValue(upper.getValue() - lower.getValue());
    });
    range.addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
        upper.setValue(range.getValue() + lower.getValue());
    });
}

我认为哪些有效,但我必须定义一个“假”&#39;属性和(我认为)添加ChangeListeners会破坏使用延迟评估的任何机会。

1 个答案:

答案 0 :(得分:1)

好的,我们需要:

  • 两个默认IntegerProperty个对象为SimpleIntegerProperty
  • 和一个来自IntegerPropertyBase的自定义IntegerProperty,可根据您的需求实施某些特殊行为。

所以我们将您的属性作为成员:

private final IntegerProperty lower = new SimpleIntegerProperty(0);
private final IntegerProperty upper = new SimpleIntegerProperty(0);
private final IntegerProperty range = new IntegerPropertyBase() {

    {
        upper.addListener(obs -> update());
        lower.addListener(obs -> update());
    }

    @Override
    public String getName() {
        return "range";
    }

    @Override
    public Object getBean() {
        return Main.this;
    }

    private void update() {
        super.set(upper.get() - lower.get());
    }

    @Override
    public void set(int newValue) {
        upper.set(lower.get() + newValue);
    }

};

我们的自定义属性基本上是一个可观察的复合数字,具有可设置的特殊情况。所以我们覆盖了一些方法并注册了必要的听众。

一些示例代码来测试/验证这一点:

private void printStats() {
    System.out.println("lower : " + lower.get() + " - upper: "
            + upper.get() + " - range: " + range.get());
    System.out.println();
}

@Override
public void start(Stage primaryStage) {

    lower.addListener(obs -> {System.out.println("Lower changed"); printStats();});
    upper.addListener(obs -> {System.out.println("Upper changed"); printStats();});
    range.addListener(obs -> {System.out.println("Range changed"); printStats();});

    System.out.println(" ######### TEST #1 #############");
    lower.set(5);

    System.out.println(" ######### TEST #2 #############");
    upper.set(5);

    System.out.println(" ######### TEST #3 #############");
    range.set(10);
}