JavaFX 绑定 StringProperty 和 IntegerProperty
JavaFX binding StringProperty and IntegerProperty
我对 JavaFX 中的绑定有疑问。假设我有映射 1:"Aaa"、2:"Bbb"、3:"Ccc" 等等。我想要的是根据此映射绑定(双向)2 个属性 IntegerProperty 和 StringProperty。如何实现?
UPD: 我将尝试描述我的用例。我有一个 class
class A {
IntegerProperty num;
...
}
但是在用户界面中我不想显示这个数值而是一些有意义的字符串。所以我想添加 StringProperty numValue
并绑定 num
和 numValue
。在 table 中,我将使用 numValue
作为 TableColumn 的 属性。当用户更改 numValue
的值时(例如通过组合框),我希望 num
自动更新。
我建议尽可能避免双向绑定,它们是有问题的1。
如果您确实需要双向绑定,那么您很幸运,您的类型之一是 String
。 bindBidirectional 方法让你指定一个 StringConverter
用于在 String
和其他类型 T
之间转换,在你的情况下 Integer
.
Map<Integer, String> m = ...;
StringProperty sp = ...;
IntegerProperty ip = ...;
Bindings.bindBidirectional(sp, ip, new StringConverter<Number>() {
@Override
public Integer fromString(String s) {
for(Integer key: m.keySet()) {
if(m.get(key).equals(s)) {
return key;
}
}
return -1; // or whatever makes sense for you
}
@Override
public String toString(Integer i) {
return m.get(i);
}
});
为什么支持类型 String
和 T
而不是任意类型 T
和 U
对我来说是个谜。
更一般地说, 你有两种类型,T
,U
,以及两个函数,f: T -> U
和 g: U -> T
,然后您想使用这两个函数在 Property<T>
和 Property<U>
之间建立双向绑定。上面的例子中,f
和g
都是由StringConverter
实现的(比如f
就是fromString
,g
就是toString
).您可以使用 ReactFX 的 Var
s2:
建立这样的双向绑定
Function<T, U> f = ...;
Function<U, T> g = ...;
Var<T> vt = ...;
Var<U> vu = ...;
Var<U> vu1 = vt.map(f).asVar(u -> vt.setValue(g.apply(u)));
Bindings.bindBidirectional(vu, vu1);
你不一定需要f
是g
的倒数,即你不需要g(f(x)) = x
,但为了避免无限循环(堆栈溢出) ,它最好快速收敛,例如f(g(f(x))) = f(x)
,或g(f(g(f(g(f(g(f(x)))))))) = g(f(g(f(g(f(x))))))
或类似的东西。
1 我意识到我只是在没有提供任何有效参数的情况下加入了这个声明。
2 Var
实际上只是一个带有一些额外方法的 Property
。
我对 JavaFX 中的绑定有疑问。假设我有映射 1:"Aaa"、2:"Bbb"、3:"Ccc" 等等。我想要的是根据此映射绑定(双向)2 个属性 IntegerProperty 和 StringProperty。如何实现?
UPD: 我将尝试描述我的用例。我有一个 class
class A {
IntegerProperty num;
...
}
但是在用户界面中我不想显示这个数值而是一些有意义的字符串。所以我想添加 StringProperty numValue
并绑定 num
和 numValue
。在 table 中,我将使用 numValue
作为 TableColumn 的 属性。当用户更改 numValue
的值时(例如通过组合框),我希望 num
自动更新。
我建议尽可能避免双向绑定,它们是有问题的1。
如果您确实需要双向绑定,那么您很幸运,您的类型之一是 String
。 bindBidirectional 方法让你指定一个 StringConverter
用于在 String
和其他类型 T
之间转换,在你的情况下 Integer
.
Map<Integer, String> m = ...;
StringProperty sp = ...;
IntegerProperty ip = ...;
Bindings.bindBidirectional(sp, ip, new StringConverter<Number>() {
@Override
public Integer fromString(String s) {
for(Integer key: m.keySet()) {
if(m.get(key).equals(s)) {
return key;
}
}
return -1; // or whatever makes sense for you
}
@Override
public String toString(Integer i) {
return m.get(i);
}
});
为什么支持类型 String
和 T
而不是任意类型 T
和 U
对我来说是个谜。
更一般地说, 你有两种类型,T
,U
,以及两个函数,f: T -> U
和 g: U -> T
,然后您想使用这两个函数在 Property<T>
和 Property<U>
之间建立双向绑定。上面的例子中,f
和g
都是由StringConverter
实现的(比如f
就是fromString
,g
就是toString
).您可以使用 ReactFX 的 Var
s2:
Function<T, U> f = ...;
Function<U, T> g = ...;
Var<T> vt = ...;
Var<U> vu = ...;
Var<U> vu1 = vt.map(f).asVar(u -> vt.setValue(g.apply(u)));
Bindings.bindBidirectional(vu, vu1);
你不一定需要f
是g
的倒数,即你不需要g(f(x)) = x
,但为了避免无限循环(堆栈溢出) ,它最好快速收敛,例如f(g(f(x))) = f(x)
,或g(f(g(f(g(f(g(f(x)))))))) = g(f(g(f(g(f(x))))))
或类似的东西。
1 我意识到我只是在没有提供任何有效参数的情况下加入了这个声明。
2 Var
实际上只是一个带有一些额外方法的 Property
。