【发布时间】:2020-06-06 01:37:56
【问题描述】:
我知道您可以使用 NumberBindings 来将 x 绑定到 y,这样如果 x 为 10,则 y 为 20。我想做一些更复杂的事情,我不确定是否可以使用绑定来实现那个目标。
我想要两组三个滑块,它们在笛卡尔坐标或球坐标中平移 3D 空间中的向量。我希望看到的是,每当修改笛卡尔滑块中的一个值时,球形滑块上的值也会相应更改,反之亦然。因此,更改一组三个中的一个值会导致更改另一组三个中的三个值。
我想尝试使用 ChangeListeners,但我进入循环,更改 A 导致重新计算 B 导致重新计算 A,并且我得到了这个网站的同名错误。我还想尝试让一个矢量对象双向绑定到两组滑块,但我遇到了同样的问题。
我想到的另一件事是让 ChangeListener 首先查看一组中的任何滑块是否被用户更改与被侦听器更改,但我还没有弄清楚如何做到这一点,甚至如果是这样,我怀疑这可能不是一种有效的方法。我要改用 ActionListener 吗?
这是我能做到的吗?
编辑:添加了 MWE
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
public class BindingProblemMWE {
private DoubleProperty xProperty;
public DoubleProperty xProperty() {
if (xProperty == null) {xProperty = new SimpleDoubleProperty(0);}
return xProperty;
}
private DoubleProperty yProperty;
public DoubleProperty yProperty() {
if (yProperty == null) {yProperty = new SimpleDoubleProperty(0);}
return yProperty;
}
private DoubleProperty zProperty;
public DoubleProperty zProperty() {
if (zProperty == null) {zProperty = new SimpleDoubleProperty(0);}
return zProperty;
}
private DoubleProperty azProperty;
public DoubleProperty azProperty() {
if (azProperty == null) {azProperty = new SimpleDoubleProperty(0);}
return azProperty;
}
private DoubleProperty elProperty;
public DoubleProperty elProperty() {
if (elProperty == null) {elProperty = new SimpleDoubleProperty(0);}
return elProperty;
}
private DoubleProperty rhoProperty;
public DoubleProperty rhoProperty() {
if (rhoProperty == null) {rhoProperty = new SimpleDoubleProperty(0);}
return rhoProperty;
}
private ChangeListener<Number> recalculateSpherical() {
return (obs, ov, nv) -> {
double x = xProperty().doubleValue();
double y = yProperty().doubleValue();
double z = zProperty().doubleValue();
azProperty.set(calculateAz(x,y,z));
elProperty.set(calculateEl(x,y,z));
rhoProperty.set(calculateRho(x,y,z));
};
}
private ChangeListener<Number> recalculateCartesian() {
return (obs, ov, nv) -> {
double az = azProperty().doubleValue();
double el = elProperty().doubleValue();
double rho = rhoProperty().doubleValue();
xProperty.set(calculateX(az, el, rho));
yProperty.set(calculateY(az, el, rho));
zProperty.set(calculateZ(az, el, rho));
};
}
private void initialize() {
xProperty().addListener(recalculateSpherical());
yProperty().addListener(recalculateSpherical());
zProperty().addListener(recalculateSpherical());
azProperty().addListener(recalculateCartesian());
elProperty().addListener(recalculateCartesian());
rhoProperty().addListener(recalculateCartesian());
xProperty().set(1);
yProperty().set(1);
zProperty().set(1);
}
private static double calculateX(double az, double el, double rho) {
return rho*Math.sin(el)*Math.cos(az);}
private static double calculateY(double az, double el, double rho) {
return rho*Math.sin(el)*Math.sin(az);}
private static double calculateZ(double az, double el, double rho) {
return rho*Math.cos(el);}
private static double calculateAz(double x, double y, double z) {
return Math.atan2(y, x);}
private static double calculateEl(double x, double y, double z) {
return Math.atan2(Math.sqrt(x*x + y*y), z);}
private static double calculateRho(double x, double y, double z) {
return Math.sqrt(x*x + y*y + z*z);}
public static void main(String [] args) {
BindingProblemMWE mwe = new BindingProblemMWE();
mwe.initialize();
}
}
【问题讨论】: