我正在尝试绑定JavaFX Circle Shape的ObjectProperty<Paint> (fillProperty)
的颜色(填充)。为此,我正在使用低级别的ObjectBinding。我想使用Color.hsb()
通过色相值创建新颜色,该色相值将根据存储在Car类中的所需SpeedProperty和汽车的实际速度进行缩放。
我尝试了多种方法来绑定Car的速度值,包括DoubleBinding来存储速度值。我还假设我的问题是由Java的懒惰引起的,因此也明确尝试了getFill()
的Circle形状。但是仍然没有成功。
Circle carShape = new Circle();
ObjectBinding<Paint> colorObjectBinding = new ObjectBinding<Paint>() {
{
super.bind(car.getSpeed().getXProperty(),car.getSpeed().getYProperty(),car.getParameters().desiredSpeedProperty());
}
@Override
protected Paint computeValue() {
double speedX = car.getSpeed().getX();
double speedY = car.getSpeed().getY();
Color color = Color.hsb(Math.sqrt(speedX*speedX+speedY*speedY)*110/car.getParameters().getDesiredSpeed(),0.94,0.94,0.94);
return color;
}
};
carShape.fillProperty().bind(colorObjectBinding);
car.speed
类型为Vector2D
,它使用DoubleProperty
存储向量的x和y值。
public class Vector2D implements Iterable<DoubleProperty>{
private DoubleProperty xProperty = new SimpleDoubleProperty(0);
private DoubleProperty yProperty = new SimpleDoubleProperty(0);
public DoubleProperty getXProperty() { return xProperty; }
public DoubleProperty getYProperty() { return yProperty; }
public double getX() { return xProperty.getValue(); }
public double getY() { return yProperty.getValue(); }
desiredSpeed
也是DoubleProperty
private DoubleProperty desiredSpeed = new SimpleDoubleProperty(0);
public double getDesiredSpeed() { return desiredSpeed.get(); }
我希望汽车的颜色随着速度的变化而变化。但是,圆在创建时仅用红色(0xf00e0ef0)
上色(我怀疑这是因为初始速度为零,因此色相为0,红色为红色)
更新
我发现了自己的错误,问题出在方法car.getSpeed()
public Vector2D getSpeed() { return new Vector2D(speed); }
如您所见,这将返回速度对象的一个副本,该副本随后被绑定,这当然是无意义的,因为该副本极有可能永远不会被更改或再次使用。 :(:0
答案 0 :(得分:1)
创建自定义绑定的最简单方法是使用Bindings
类的实用程序(在您的情况下为Bindings#createObjectBinding()
)。例如:
Bindings.createObjectBinding(() -> {
double speedX = car.getSpeed().getX();
double speedY = car.getSpeed().getY();
Color color = Color.hsb(Math.sqrt(speedX*speedX+speedY*speedY)*110/car.getParameters().getDesiredSpeed(),0.94,0.94,0.94);
return color;
}, car.getSpeed().getXProperty(),car.getSpeed().getYProperty(),car.getParameters().desiredSpeedProperty()) ;
此外,还有类似的类似问题,您可能会找到答案。 How to create custom binding types in JavaFx
答案 1 :(得分:0)
这是一个有效的最小,完整,可验证的示例,它说明了我如何最终bind
形状为fillProperty
的{{1}}。时间轴只是检查颜色变化是否正在响应的一种方式。
Circle
以及import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
import tomek.szypula.math.Vector2D;
import java.util.concurrent.Callable;
public class ColorBindingTest extends Application {
public static void main(String[] args) {
launch(args);
}
final private double maxSpeed = 10;
final private double maxColor = 110; //Green
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Scene theScene = new Scene( root,1100, 800 );
primaryStage.setTitle("ColorBindingTest");
primaryStage.setScene(theScene);
Circle carShape = new Circle();
Vector2D speed = new Vector2D();
carShape.setCenterX(100);
carShape.setCenterY(100);
carShape.setRadius(10);
root.getChildren().add(carShape);
ObjectBinding<Color> colorObjectBinding1 = Bindings.createObjectBinding(
new Callable<Color>() {
@Override
public Color call() throws Exception {
double speedX = speed.getX();
double speedY = speed.getY();
Color color = Color.hsb(Math.sqrt(speedX*speedX+speedY*speedY)*maxColor/maxSpeed,0.94,0.94,0.94);
return color;
}
},speed.getXProperty(),speed.getYProperty()
);
carShape.fillProperty().bind(colorObjectBinding1);
Timeline timeline = new Timeline(new KeyFrame(
Duration.millis(200),
ae -> {
speed.setX(Math.random()*maxSpeed);
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
primaryStage.show();
}
}
类的最小版本,也可以将其替换为Vector2D
DoubleProperty