在我的程序中,我希望对象显示它们从一个点移动到另一个点。我使用了TranslateTransition
。为了使它工作,我需要给它一个起始位置,在我的例子中,是到起始节点的距离。
问题是,两个节点位于不同的容器中,因此在计算中使用layoutX
和layoutY
将无效。
在下面的代码中,我使用localToScene
方法将相对于本地节点的坐标转换为场景。然后我做了一点减法来得到两个节点之间相对于移动节点的距离。
import com.neonorb.commons.log.Log;
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Node;
import javafx.scene.Parent;
import sun.reflect.generics.reflectiveObjects.LazyReflectiveObjectGenerator;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
/**
* Created by chris on 8/23/15.
*/
public class TranslateUtils {
public static DoubleProperty getTranslateX(Node translatingNode, Node otherNode) {
DoubleProperty ret = new SimpleDoubleProperty();
Platform.runLater(() -> {
List<Observable> dependencies = getAllParents(translatingNode).stream().map(Node::layoutXProperty).collect(Collectors.toList());
dependencies.addAll(getAllParents(otherNode).stream().map(Node::layoutXProperty).collect(Collectors.toList()));
ret.bind(Bindings.createDoubleBinding(new Callable<Double>() {
@Override
public Double call() throws Exception {
Log.debug("recalculating x");
return otherNode.localToScene(otherNode.getBoundsInLocal()).getMinX() - translatingNode.localToScene(translatingNode.getBoundsInLocal()).getMinX();
}
}, dependencies.toArray(new Observable[dependencies.size()])));
});
return ret;
}
public static DoubleProperty getTranslateY(Node translatingNode, Node otherNode) {
DoubleProperty ret = new SimpleDoubleProperty();
Platform.runLater(() -> {
List<Observable> dependencies = getAllParents(translatingNode).stream().map(Node::layoutXProperty).collect(Collectors.toList());
dependencies.addAll(getAllParents(otherNode).stream().map(Node::layoutXProperty).collect(Collectors.toList()));
ret.bind(Bindings.createDoubleBinding(new Callable<Double>() {
@Override
public Double call() throws Exception {
Log.debug("recalculating y");
return otherNode.localToScene(otherNode.getBoundsInLocal()).getMinY() - translatingNode.localToScene(translatingNode.getBoundsInLocal()).getMinY();
}
}, dependencies.toArray(new Observable[dependencies.size()])));
});
return ret;
}
private static List<Parent> getAllParents(Node node) {
List<Parent> parents = new ArrayList<Parent>();
Parent parent = node.getParent();
if (parent != null) {
parents.addAll(getAllParents(parent));
parents.add(parent);
}
return parents;
}
}
您可以使用以下方法测试代码:
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.controlsfx.tools.Borders;
import java.io.IOException;
/**
* Created by chris on 7/20/15.
*/
public class Test extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException {
BorderPane borderPane = new BorderPane();
Label translatingNode = new Label("translating node");
HBox translatingHBox = new HBox(translatingNode);
translatingHBox.setAlignment(Pos.CENTER);
borderPane.setTop(translatingHBox);
Label referenceNode = new Label("reference node");
HBox referenceHBox = new HBox(referenceNode);
referenceHBox.setAlignment(Pos.CENTER_RIGHT);
borderPane.setBottom(referenceHBox);
TranslateTransition translateTransition = new TranslateTransition(Duration.seconds(3), translatingNode);
translateTransition.fromXProperty().bind(TranslateUtils.getTranslateX(translatingNode, referenceNode));
translateTransition.fromYProperty().bind(TranslateUtils.getTranslateY(translatingNode, referenceNode));
translateTransition.setToX(0);
translateTransition.setToY(0);
Button playButton = new Button("play");
playButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
translateTransition.play();
}
});
borderPane.setCenter(playButton);
primaryStage.setScene(new Scene(borderPane));
primaryStage.show();
}
}
您可以第一次成功播放动画,但请尝试调整窗口大小。翻译地点不会更新。
答案 0 :(得分:1)
您未包含layoutXProperty
本身的translatingNode
。要修复您的演示,只需将Node本身包含在其父项列表中:
private static List<Node> getAllParents(Node node) {
List<Node> parents = new ArrayList<Node>();
if (node != null) {
parents.addAll(getAllParents(node.getParent()));
parents.add(node);
}
return parents;
}
答案 1 :(得分:0)
我最终使用自定义方法来查找全球位置:
private static double getGlobalX(Node node) {
if (node == null) {
return 0.0;
}
double parentGlobalX = getGlobalX(node.getParent());
return node.getLayoutX() - parentGlobalX;
}
private static double getGlobalY(Node node) {
if (node == null) {
return 0.0;
}
double parentGlobalY = getGlobalY(node.getParent());
return parentGlobalY - node.getLayoutY();
}