JavaFX - 在 GridPane 中循环遍历 TextFields 并暂停更新文本
JavaFX - Loop through TextFields in a GridPane and update text with pause
我有一个包含 20 个空文本字段的 GridPane。我想遍历每个文本字段并使用 ArrayList 中的值更新每个文本字段中的文本,每个文本字段之间暂停约 1 秒。想不通了。
我这样创建 GridPane:
GridPane grid = new GridPane();
Scene drawing = new Scene(new VBox(grid), 500, 200);
primaryStage.setScene(drawing);
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 10; ++j) {
TextField tf = new TextField();
tf.setPrefHeight(50);
tf.setPrefWidth(50);
tf.setAlignment(Pos.CENTER);
tf.setEditable(false);
grid.add(tf, j, i);
}
}
我现在想遍历每个文本框并添加文本,中间有一个停顿。在循环中使用 Thread.sleep() 会导致应用程序崩溃。我试过这样的 PauseTransition:
ArrayList<Integer> numsDrawn= game.draw();
int count = 0;
for (Node node : grid.getChildren()) {
PauseTransition pause = new PauseTransition(Duration.seconds(1));
pause.setOnFinished(e -> ((TextField)node).setText(Integer.toString(numsDrawn.get(count))));
pause.play();
count++;
}
但我收到错误 在封闭范围内定义的局部变量计数必须是最终的或实际上是最终的。
Count 必须能够更改,以便我可以遍历 numsDrawn 列表并向每个 TextField 添加不同的文本。我试过创建一个单独的事件处理程序而不是 lambda,但在计数时遇到相同的错误。
如果有人可以就如何完成这项看似简单的任务提供建议,我将不胜感激。
根据错误消息,您应该将 final
变量传递给 numsDrawn.get
方法,所以我会尝试这样做:
ArrayList<Integer> numsDrawn= game.draw();
int count = 0;
for (Node node : grid.getChildren()) {
PauseTransition pause = new PauseTransition(Duration.seconds(1));
final int countFinal = count;
pause.setOnFinished(e -> ((TextField)node).setText(Integer.toString(numsDrawn.get(countFinal))));
pause.play();
count++;
}
所以我自己想出来了。使用文本字段创建网格时,我还将每个文本字段添加到 ArrayList tfs 以便我可以单独访问每个字段以稍后添加文本。然后,我创建了一个新线程,将文本添加到 numsDrawn 中的每个字段,如下所示:
new Thread(() -> {
for (int i = 0; i < 20; ++i) {
final int j = i;
Platform.runLater(() -> tfs.get(j).setText(Integer.toString(numsDrawn.get(j))));
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}).start();
在这种情况下我会推荐 Timeline
。将持续时间设置为一秒,将循环计数设置为 GridPane
.
中的 TextFields
个数
import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class App extends Application {
Timeline timeline;
AtomicInteger counter = new AtomicInteger();
@Override
public void start(Stage primaryStage) throws Exception {
GridPane gridPane = new GridPane();
gridPane.add(new TextField(), 0, 0);
gridPane.add(new TextField(), 0, 1);
gridPane.add(new TextField(), 0, 2);
gridPane.add(new TextField(), 0, 3);
gridPane.add(new TextField(), 0, 4);
gridPane.add(new TextField(), 0, 5);
gridPane.add(new TextField(), 0, 6);
gridPane.add(new TextField(), 0, 7);
gridPane.setMaxSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);
timeline = new Timeline(new KeyFrame(Duration.seconds(1), (ActionEvent t) -> {
System.out.println(counter.get());
TextField tempTextField = (TextField)gridPane.getChildren().get(counter.get());
tempTextField.setText(Integer.toString(counter.getAndIncrement()));
}));
timeline.setCycleCount(gridPane.getChildren().size());
Button btnStartTimeline = new Button("Start Timeline");
btnStartTimeline.setOnAction((t) -> {
timeline.play();
});
VBox root = new VBox(gridPane, btnStartTimeline);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 700, 700);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
我有一个包含 20 个空文本字段的 GridPane。我想遍历每个文本字段并使用 ArrayList 中的值更新每个文本字段中的文本,每个文本字段之间暂停约 1 秒。想不通了。
我这样创建 GridPane:
GridPane grid = new GridPane();
Scene drawing = new Scene(new VBox(grid), 500, 200);
primaryStage.setScene(drawing);
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 10; ++j) {
TextField tf = new TextField();
tf.setPrefHeight(50);
tf.setPrefWidth(50);
tf.setAlignment(Pos.CENTER);
tf.setEditable(false);
grid.add(tf, j, i);
}
}
我现在想遍历每个文本框并添加文本,中间有一个停顿。在循环中使用 Thread.sleep() 会导致应用程序崩溃。我试过这样的 PauseTransition:
ArrayList<Integer> numsDrawn= game.draw();
int count = 0;
for (Node node : grid.getChildren()) {
PauseTransition pause = new PauseTransition(Duration.seconds(1));
pause.setOnFinished(e -> ((TextField)node).setText(Integer.toString(numsDrawn.get(count))));
pause.play();
count++;
}
但我收到错误 在封闭范围内定义的局部变量计数必须是最终的或实际上是最终的。
Count 必须能够更改,以便我可以遍历 numsDrawn 列表并向每个 TextField 添加不同的文本。我试过创建一个单独的事件处理程序而不是 lambda,但在计数时遇到相同的错误。
如果有人可以就如何完成这项看似简单的任务提供建议,我将不胜感激。
根据错误消息,您应该将 final
变量传递给 numsDrawn.get
方法,所以我会尝试这样做:
ArrayList<Integer> numsDrawn= game.draw();
int count = 0;
for (Node node : grid.getChildren()) {
PauseTransition pause = new PauseTransition(Duration.seconds(1));
final int countFinal = count;
pause.setOnFinished(e -> ((TextField)node).setText(Integer.toString(numsDrawn.get(countFinal))));
pause.play();
count++;
}
所以我自己想出来了。使用文本字段创建网格时,我还将每个文本字段添加到 ArrayList tfs 以便我可以单独访问每个字段以稍后添加文本。然后,我创建了一个新线程,将文本添加到 numsDrawn 中的每个字段,如下所示:
new Thread(() -> {
for (int i = 0; i < 20; ++i) {
final int j = i;
Platform.runLater(() -> tfs.get(j).setText(Integer.toString(numsDrawn.get(j))));
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}).start();
在这种情况下我会推荐 Timeline
。将持续时间设置为一秒,将循环计数设置为 GridPane
.
TextFields
个数
import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class App extends Application {
Timeline timeline;
AtomicInteger counter = new AtomicInteger();
@Override
public void start(Stage primaryStage) throws Exception {
GridPane gridPane = new GridPane();
gridPane.add(new TextField(), 0, 0);
gridPane.add(new TextField(), 0, 1);
gridPane.add(new TextField(), 0, 2);
gridPane.add(new TextField(), 0, 3);
gridPane.add(new TextField(), 0, 4);
gridPane.add(new TextField(), 0, 5);
gridPane.add(new TextField(), 0, 6);
gridPane.add(new TextField(), 0, 7);
gridPane.setMaxSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);
timeline = new Timeline(new KeyFrame(Duration.seconds(1), (ActionEvent t) -> {
System.out.println(counter.get());
TextField tempTextField = (TextField)gridPane.getChildren().get(counter.get());
tempTextField.setText(Integer.toString(counter.getAndIncrement()));
}));
timeline.setCycleCount(gridPane.getChildren().size());
Button btnStartTimeline = new Button("Start Timeline");
btnStartTimeline.setOnAction((t) -> {
timeline.play();
});
VBox root = new VBox(gridPane, btnStartTimeline);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 700, 700);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}