В моей программе JavaFX в настоящее время весь мой код выполняется в потоке приложений JavaFX (включая код игровой логики, который не обязательно обновляет интерфейс). Я читал, что вы должны запускать код не-пользовательского интерфейса в отдельном фоновом потоке, а затем обновлять его соответствующим образом в потоке приложений JavaFX, используя Platform.runLater
или Tasks
, чтобы пользовательский интерфейс не блокировался, но я все еще в замешательстве почему пользовательский интерфейс зависает, когда я просто вызываю myFlowPane.getChildren().remove()
в потоке приложений JavaFX.
Надеемся, что следующий код обеспечивает достаточный контекст
hand.getTiles().addListener((ListChangeListener<ObservableTile>) change -> {
while (change.next()) {
if (change.wasAdded()) {
for (Tile t : change.getAddedSubList()) {
var btn = tileButtonFactory.newTileButton(t);
fpHand.getChildren().add(change.getFrom(), btn);
}
} else if (change.wasRemoved()) {
// Player can only remove 1 tile at a time
Tile tile = change.getRemoved().get(0);
fpHand.getChildren().removeIf(node -> ((TileButton)node).getTile().equals(tile));
}
}
});
У меня есть FlowPane, который содержит кучу кнопок, и я слушаю ObservableList
, который содержит кучу плиток. Когда этот список плиток изменяется, я хочу соответствующим образом обновить FlowPane, чтобы при создании новых плиток я создал кнопку в FlowPane. Точно так же, когда плитка удаляется из этого списка плиток, я хочу, чтобы кнопка, содержащая эту плитку, была удалена из FlowPane.
Итак, из того, что я нашел в Интернете, слушатели событий запускаются в потоке приложений JavaFX. Это означает, что приведенный выше код выполняется в потоке приложения JavaFX. Когда я добавляю кнопку в FlowPane, пользовательский интерфейс не останавливается / блокируется fpHand.getChildren().add()
. С другой стороны, когда я удаляю кнопку из FlowPane, пользовательский интерфейс зависает на fpHand.getChildren.remove
.
Однако, когда я обертываю fpHand.getChildren.remove()
вызов Platform.runLater()
, пользовательский интерфейс отзывчив и не зависает. Почему это? Весь код в настоящее время выполняется в потоке приложений JavaFX.
Кроме того, у меня похожая проблема с другой частью моего кода. У меня есть GridPane с 128 ячейками (у каждой ячейки есть HBox), и мне нужно обновить таблицу. У меня есть следующий код:
private void updateTable() {
Platform.runLater(() -> {
clearTable();
table.forEach(this::addTilesToTable);
});
}
private void clearTable() {
for (int row = 0; row < gpTable.getRowCount(); row++) {
for (int col = 0; col < gpTable.getColumnCount(); col++) {
getCellFromGridPane(row, col).ifPresent(hbox -> hbox.getChildren().clear());
}
}
}
Если я удаляю Platform.runLater()
, пользовательский интерфейс не зависает полностью, но все плитки, которые я добавил ранее, сразу появляются, как будто на столе есть невидимая плитка, и поэтому я не могу добавить плитку там, хотя он должен быть пустым. Функция updateTable()
также вызывается в потоке приложений JavaFX и в прослушивателе событий. Кажется, что hbox.getChildren.clear()
не вызывается должным образом, если я удаляю Platform.runLater()
.