如何在 JavaFX 中交换两个 GridPane 节点?
Posted
技术标签:
【中文标题】如何在 JavaFX 中交换两个 GridPane 节点?【英文标题】:How to swap two GridPane nodes in JavaFX? 【发布时间】:2021-11-04 22:22:04 【问题描述】:我想在 javafx 的 GUI 中模拟数组元素的交换。
我有一个网格窗格Memory
,它就像一个数组。网格的第 1 行只有数组。
在每一行/列中,我添加了一个具有图像视图和标签的堆栈窗格。
我想更改当前节点及其下一个节点的图像视图。连同数据。
我尝试通过循环执行此操作,但未看到结果。 所以我使用了一个线程来进行背景图像交换,但这不允许交换标签值。 这是我在更改背景时没有交换的最接近的结果。
public void insertFront()
System.out.println("InsertList before insert "+ insertList.size()+" : "+insertList);
if (insertList.size() == 0)
ObservableList<Node> nodes = insertArr[0].getChildren();
Label temp = (Label) nodes.get(1);
insertList.add(random.nextInt(999));
temp.setText(""+insertList.get(0));
else
if (insertList.size() < max)
new Thread(()->
for (int i = insertList.size()-1; i >= 0; i--)
ObservableList<Node> currNodes = insertArr[i].getChildren();
ImageView temp = (ImageView) currNodes.get(0);
temp.setImage(current);
ObservableList<Node> nextNodes = insertArr[i+1].getChildren();
ImageView tempNext = (ImageView) nextNodes.get(0);
tempNext.setImage(next);
Label tempLabel = (Label) currNodes.get(1);
Label tempNextLabel = (Label) nextNodes.get(1);
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
temp.setImage(allocated);
tempNext.setImage(allocated);
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
).start();
for (int i = insertList.size()-1; i >= 0; i--)
ObservableList<Node> currNodes = insertArr[i].getChildren();
ObservableList<Node> nextNodes = insertArr[i+1].getChildren();
Label tempLabel = (Label) currNodes.get(1);
Label tempNextLabel = (Label) nextNodes.get(1);
tempNextLabel.setText(tempLabel.getText());
tempLabel.setText("");
ObservableList<Node> nodes = insertArr[0].getChildren();
Label temp = (Label) nodes.get(1);
insertList.add(0, random.nextInt(999));
temp.setText("" + insertList.get(0));
else
insertList.removeAll(insertList);
fillInsert();
insertFront();
System.out.println("InsertList after insert "+ (insertList.size())+" : "+insertList);
但这没有同步。我试图实现的是至少先显示背景的交换,然后直接更新行。 但是因为线程没有同步,所以转换很慢并且网格行被更新了。
我需要帮助至少同步线程,以便首先显示转换。然后行被改变。
【问题讨论】:
设计说明:您应该为此使用javafx.animation
API,而不是线程。
@Slaw 你能做一个演示吗?我是 javafx 的初学者。谢谢。
更多帮助请发帖minimal reproducible example
【参考方案1】:
不确定我是否完全理解,但我认为您需要一种方法来交换 GridPane 中的两个节点。
这是如何工作的完整演示。
GridItem.java
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
public class GridItem extends StackPane
private String text;
private Color backgroundColor;
public GridItem(String text, Color color)
setText(text);
setBackgroundColor(color);
Label textLabel = new Label(text);
getChildren().add(textLabel);
StackPane.setAlignment(textLabel, Pos.CENTER);
setBackground(new Background(new BackgroundFill(color, CornerRadii.EMPTY, Insets.EMPTY)));
setPrefSize(100, 100);
public Color getBackgroundColor()
return backgroundColor;
public void setBackgroundColor(Color backgroundColor)
this.backgroundColor = backgroundColor;
public String getText()
return text;
public void setText(String text)
this.text = text;
HelloApplication.java
import java.util.Random;
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class HelloApplication extends Application
@Override
public void start(Stage stage)
GridPane gridPane = new GridPane();
for (int i = 0; i < 16; i++)
gridPane.add(
new GridItem("Hello " + i,
Color.color(new Random().nextDouble(), new Random().nextDouble(), new Random().nextDouble())), i % 4, i / 4);
Scene scene = new Scene(gridPane, 900, 650);
scene.setOnMouseClicked(e -> swapGridPane(gridPane, 0, 0, 3, 3, true));
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
public static void swapGridPane(GridPane gridPane, int i1, int j1, int i2, int j2, boolean animate)
Node node1 = getNodeByRowColumnIndex(i1, j1, gridPane);
Node node2 = getNodeByRowColumnIndex(i2, j2, gridPane);
gridPane.getChildren().removeAll(node1, node2);
gridPane.add(node1, i2, j2);
gridPane.add(node2, i1, j1);
if (animate)
fadeIn(node1);
fadeIn(node2);
public static void fadeIn(Node node)
FadeTransition fadeTransition = new FadeTransition(Duration.millis(200), node);
fadeTransition.setFromValue(0);
fadeTransition.setToValue(1);
fadeTransition.play();
public static Node getNodeByRowColumnIndex(final int row, final int column, GridPane gridPane)
return gridPane.getChildren().stream()
.filter(node -> GridPane.getRowIndex(node) == row)
.filter(node -> GridPane.getColumnIndex(node) == column)
.findFirst().get();
public static void main(String[] args)
launch();
【讨论】:
是的,这有我需要的...非常感谢!!以上是关于如何在 JavaFX 中交换两个 GridPane 节点?的主要内容,如果未能解决你的问题,请参考以下文章