如何在 JavaFX 中交换两个 GridPane 节点?
How to swap two GridPane nodes in JavaFX?
我想在 javafx 的 GUI 中模拟数组元素的交换。
我有一个网格窗格 Memory
,它就像一个数组。网格的第 1 行只有数组。
在每个 row/col 中,我添加了一个具有图像视图和标签的堆栈窗格。
我想更改当前节点及其下一个节点的图像视图。连同数据。
我尝试通过循环进行,但没有看到结果。
所以我使用了一个线程来交换背景图像,但不允许交换标签值。
这是我在更改背景时没有交换的最接近的。
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);
}
但这不是同步的。我试图实现的是至少先显示背景的交换,然后直接更新行。
但是因为线程不同步,转换很慢并且网格行被更新。
我至少需要同步线程方面的帮助,以便首先显示转换。然后换行。
不确定我是否完全理解,但我认为您需要一种方法来交换 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 的 GUI 中模拟数组元素的交换。
我有一个网格窗格 Memory
,它就像一个数组。网格的第 1 行只有数组。
在每个 row/col 中,我添加了一个具有图像视图和标签的堆栈窗格。
我想更改当前节点及其下一个节点的图像视图。连同数据。
我尝试通过循环进行,但没有看到结果。 所以我使用了一个线程来交换背景图像,但不允许交换标签值。 这是我在更改背景时没有交换的最接近的。
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);
}
但这不是同步的。我试图实现的是至少先显示背景的交换,然后直接更新行。 但是因为线程不同步,转换很慢并且网格行被更新。
我至少需要同步线程方面的帮助,以便首先显示转换。然后换行。
不确定我是否完全理解,但我认为您需要一种方法来交换 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();
}
}