HBox 错误地显示节点,即使 getChildren() 以正确的顺序显示它们
HBox displaying Nodes incorrectly, even though getChildren() displays them in the correct order
好的,就这样吧,我折腾了一整天都没有找到解决方案:
我在屏幕上显示了一个 HBox,它包含多个 StackPanel 元素,每个元素包含一个 Circle 和一个 Label 元素,因此两者都显示在它们自己的顶部。 StackPanels 是 HBox 的节点,是基于数组而不是通过 xfml 文件添加的。 HBox 在 VBox 中,其中包含 3 个与此处无关的其他元素。
我的 objective 是使用动画切换其中两个节点,这是我使用具有弧形路径的 PathTransition 创建的。我同时有两个这样的动画运行,一个是节点到达目的地,一个是到达当前位置。
动画完成后,我使用switchNode()函数来切换两个节点,因为我想改变它们的顺序,因为我想继续执行动画,而动画本身并没有改变它们的顺序,只有位置。例如,HBox.getChildren().etc(将其转换为文本)如果我切换第 0 和第三个索引。
貌似交换成功了,问题是交换的位置没有显示出来
public class AnimationController2 {
private int[] arr = new int[] { 0, 1, 2, 3, 4, 5 };
@FXML
private VBox vbox;
@FXML
private HBox content;
@FXML
private HBox indexes;
@FXML
private void switchToInput() throws IOException {
App.setRoot("input");
}
@FXML
private void repeat() {
animate(0, 3); //should work for any index and be repeatable
}
public void initialize() {
addElements();
}
public void animate(int from, int to) {
PathTransition move1 = new PathTransition();
PathTransition move2 = new PathTransition();
Node node1 = content.getChildren().get(from);
Node node2 = content.getChildren().get(to);
move1.setNode(node1);
move2.setNode(node2);
move1.setDuration(Duration.seconds(3));
move2.setDuration(Duration.seconds(3));
move1.setPath(makePath(node1, node2, true));
move2.setPath(makePath(node2, node1, false));
move2.setOnFinished(b -> {
switchNode(from, to);
});
move1.play();
move2.play();
}
public void switchNode(int a, int b) {
ObservableList<Node> workingCollection = FXCollections.observableArrayList(content.getChildren());
/*
* Debugging
* System.out.println(" ");
* System.out.println("Original: ");
* for (Node i : workingCollection) {
* Label aa = (Label) ((StackPane) i).getChildren().get(1);
* System.out.print(aa.getText() + " ");
* }
*/
Collections.swap(workingCollection, a, b);
/*
* Debugging
* System.out.println(" ");
* System.out.println("Switched: ");
* for (Node i : workingCollection) {
* Label aa = (Label) ((StackPane) i).getChildren().get(1);
* System.out.print(aa.getText() + " ");
* }
*/
content.getChildren().setAll(workingCollection);
}
public Path makePath(Node from, Node to, boolean right) {
// creating variables
double distance = to.getLayoutX() - from.getLayoutX();
double x = from.boundsInLocalProperty().get().getCenterX();
double y = from.boundsInLocalProperty().get().getCenterY();
double fromX = x;
double fromY = y;
double toX = x + distance; // 300
double toY = y;
ArcTo arcTo = new ArcTo();
arcTo.setLargeArcFlag(false);
arcTo.setSweepFlag(true);
arcTo.setRadiusX((toX + fromX) / 2);
arcTo.setRadiusY(right ? 200 : distance / 3); // optimal values
arcTo.setX(toX);
arcTo.setY(toY);
Path path = new Path();
path.getElements().addAll(new MoveTo(fromX, fromY), arcTo);
return path;
}
public void addElements() {
for (int i = 0; i < arr.length; i++) {
Circle circle = new Circle(30, 30, 30);
circle.setFill(Color.BLUE);
Label label = new Label(arr[i] + "");
label.setTextFill(Color.BLACK);
StackPane join = new StackPane();
join.getChildren().addAll(circle, label);
content.getChildren().add(join);
Label index = new Label(i + "");
indexes.getChildren().add(index);
indexes.setSpacing(62);
}
}
}
public class App extends Application {
private static Scene scene;
@Override
public void start(Stage stage) throws IOException {
scene = new Scene(loadFXML("animation"), 640, 480);
stage.setScene(scene);
stage.setTitle("Array2Tree");
stage.show();
}
static void setRoot(String fxml) throws IOException {
scene.setRoot(loadFXML(fxml));
}
private static Parent loadFXML(String fxml) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
return fxmlLoader.load();
}
public static void main(String[] args) {
launch(args);
}
}
FXML
<VBox fx:id = "vbox" alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.example.AnimationController2">
<children>
<HBox alignment="CENTER" spacing="10.0" fx:id = "content" ></HBox>
<HBox alignment="CENTER" spacing="10.0" fx:id = "indexes" ></HBox>
<Label text="Animation View" />
<Button fx:id="InputButton" onAction="#switchToInput" text="Switch to Input" />
<Button fx:id = "Repeat" onAction="#repeat" text="Repeat" />
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
感谢@jewelsea 的评论。
添加
解决了我的问题
workingCollection.get(a).setTranslateX(0);
workingCollection.get(b).setTranslateX(0);
之前
Collections.swap(workingCollection, a, b);
好的,就这样吧,我折腾了一整天都没有找到解决方案:
我在屏幕上显示了一个 HBox,它包含多个 StackPanel 元素,每个元素包含一个 Circle 和一个 Label 元素,因此两者都显示在它们自己的顶部。 StackPanels 是 HBox 的节点,是基于数组而不是通过 xfml 文件添加的。 HBox 在 VBox 中,其中包含 3 个与此处无关的其他元素。
我的 objective 是使用动画切换其中两个节点,这是我使用具有弧形路径的 PathTransition 创建的。我同时有两个这样的动画运行,一个是节点到达目的地,一个是到达当前位置。
动画完成后,我使用switchNode()函数来切换两个节点,因为我想改变它们的顺序,因为我想继续执行动画,而动画本身并没有改变它们的顺序,只有位置。例如,HBox.getChildren().etc(将其转换为文本)如果我切换第 0 和第三个索引。
貌似交换成功了,问题是交换的位置没有显示出来
public class AnimationController2 {
private int[] arr = new int[] { 0, 1, 2, 3, 4, 5 };
@FXML
private VBox vbox;
@FXML
private HBox content;
@FXML
private HBox indexes;
@FXML
private void switchToInput() throws IOException {
App.setRoot("input");
}
@FXML
private void repeat() {
animate(0, 3); //should work for any index and be repeatable
}
public void initialize() {
addElements();
}
public void animate(int from, int to) {
PathTransition move1 = new PathTransition();
PathTransition move2 = new PathTransition();
Node node1 = content.getChildren().get(from);
Node node2 = content.getChildren().get(to);
move1.setNode(node1);
move2.setNode(node2);
move1.setDuration(Duration.seconds(3));
move2.setDuration(Duration.seconds(3));
move1.setPath(makePath(node1, node2, true));
move2.setPath(makePath(node2, node1, false));
move2.setOnFinished(b -> {
switchNode(from, to);
});
move1.play();
move2.play();
}
public void switchNode(int a, int b) {
ObservableList<Node> workingCollection = FXCollections.observableArrayList(content.getChildren());
/*
* Debugging
* System.out.println(" ");
* System.out.println("Original: ");
* for (Node i : workingCollection) {
* Label aa = (Label) ((StackPane) i).getChildren().get(1);
* System.out.print(aa.getText() + " ");
* }
*/
Collections.swap(workingCollection, a, b);
/*
* Debugging
* System.out.println(" ");
* System.out.println("Switched: ");
* for (Node i : workingCollection) {
* Label aa = (Label) ((StackPane) i).getChildren().get(1);
* System.out.print(aa.getText() + " ");
* }
*/
content.getChildren().setAll(workingCollection);
}
public Path makePath(Node from, Node to, boolean right) {
// creating variables
double distance = to.getLayoutX() - from.getLayoutX();
double x = from.boundsInLocalProperty().get().getCenterX();
double y = from.boundsInLocalProperty().get().getCenterY();
double fromX = x;
double fromY = y;
double toX = x + distance; // 300
double toY = y;
ArcTo arcTo = new ArcTo();
arcTo.setLargeArcFlag(false);
arcTo.setSweepFlag(true);
arcTo.setRadiusX((toX + fromX) / 2);
arcTo.setRadiusY(right ? 200 : distance / 3); // optimal values
arcTo.setX(toX);
arcTo.setY(toY);
Path path = new Path();
path.getElements().addAll(new MoveTo(fromX, fromY), arcTo);
return path;
}
public void addElements() {
for (int i = 0; i < arr.length; i++) {
Circle circle = new Circle(30, 30, 30);
circle.setFill(Color.BLUE);
Label label = new Label(arr[i] + "");
label.setTextFill(Color.BLACK);
StackPane join = new StackPane();
join.getChildren().addAll(circle, label);
content.getChildren().add(join);
Label index = new Label(i + "");
indexes.getChildren().add(index);
indexes.setSpacing(62);
}
}
}
public class App extends Application {
private static Scene scene;
@Override
public void start(Stage stage) throws IOException {
scene = new Scene(loadFXML("animation"), 640, 480);
stage.setScene(scene);
stage.setTitle("Array2Tree");
stage.show();
}
static void setRoot(String fxml) throws IOException {
scene.setRoot(loadFXML(fxml));
}
private static Parent loadFXML(String fxml) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
return fxmlLoader.load();
}
public static void main(String[] args) {
launch(args);
}
}
FXML
<VBox fx:id = "vbox" alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.example.AnimationController2">
<children>
<HBox alignment="CENTER" spacing="10.0" fx:id = "content" ></HBox>
<HBox alignment="CENTER" spacing="10.0" fx:id = "indexes" ></HBox>
<Label text="Animation View" />
<Button fx:id="InputButton" onAction="#switchToInput" text="Switch to Input" />
<Button fx:id = "Repeat" onAction="#repeat" text="Repeat" />
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
感谢@jewelsea 的评论。
添加
解决了我的问题workingCollection.get(a).setTranslateX(0);
workingCollection.get(b).setTranslateX(0);
之前
Collections.swap(workingCollection, a, b);