Изменение элементов в GridPane с использованием другого потока - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть GridPane с изображением на нем.Мне бы хотелось, чтобы изображение меняло свою позицию (переходило к другому дочернему узлу сетки) каждые 2 секунды.Однако, когда я запустил программу, используя другой поток, я получаю: Нет ошибки потока приложения FX. Любая помощь приветствуется!

Я также пытался использовать Platform.runLater, но он все еще не 'т работа.Также, прочитав различные посты, я узнал, что GridPane не является потокобезопасным.Есть ли способ обойти это?

public class BoardController implements Initializable {
    @FXML
    private GridPane board;
    @FXML
    private Text position;

    String pikachuPos = "";
    String pokeballPos = "";
    int i = 0;
    int j = 0;
    boolean selectPikachu = true;
    int count = 0;

    int pikachuRow = 0;
    int pikachuCol = 0;
    int pokeballRow = 0;
    int pokeballCol = 0;

    ImageView pikachu = new ImageView(getClass().getResource("pikachu.png").toExternalForm());
    ImageView pokeball = new ImageView(getClass().getResource("pokeball.png").toExternalForm());

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        pikachu.setFitWidth(30);
        pikachu.setFitHeight(30);
        pokeball.setFitWidth(30);
        pokeball.setFitHeight(30);

        position.setVisible(true);
        if (count == 2) {
            System.out.println("2");
        }
        boolean pikachu = true;

        Button[][] buttons = new Button[10][10];
        Button b;
        for (i = 0; i < 10; i++) {
            for (j = 0; j < 10; j++) {
                b = new Button(j + " " + i);
                buttons[i][j] = b;
                buttons[i][j].setOnAction((event) -> {
                    if (this.selectPikachu) {
                        Button button = (Button) event.getSource();
                        this.pikachuPos = button.getText();
                        this.selectPikachu = false;
                        this.position.setText("Choose Pokeball position");
                    } else {
                        Button button = (Button) event.getSource();
                        this.pokeballPos = button.getText();
                        this.position.setText("");
                        try {
                            this.play();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(BoardController.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }

                });

                board.add(buttons[i][j], i, j);
                GridPane.setHalignment(buttons[i][j], HPos.CENTER);
            }
        }
    }

    public void play() throws InterruptedException {

        Node node = board.getChildren().get(0);
        board.getChildren().clear();
        board.getChildren().add(0, node);

        String[] pikachuDetails = pikachuPos.split(" ");
        String[] pokeballDetails = pokeballPos.split(" ");

        pikachuRow = Integer.parseInt(pikachuDetails[1]);
        pikachuCol = Integer.parseInt(pikachuDetails[0]);

        pokeballRow = Integer.parseInt(pokeballDetails[1]);
        pokeballCol = Integer.parseInt(pokeballDetails[0]);

        ImageView pokeball = new ImageView(getClass().getResource("pokeball.png").toExternalForm());
        pokeball.setFitWidth(30);
        pokeball.setFitHeight(30);

        ImageView pikachu = new ImageView(getClass().getResource("pikachu.png").toExternalForm());
        pikachu.setFitWidth(30);
        pikachu.setFitHeight(30);

        GridPane.setHalignment(pokeball, HPos.CENTER);
        board.add(pokeball, pokeballRow, pokeballCol);

        GridPane.setHalignment(pikachu, HPos.CENTER);
        board.add(pikachu, pikachuRow, pikachuCol);

        startTask();

    }

    public void startTask() {
        // Create a Runnable
        Runnable task = new Runnable() {
            public void run() {
                runTask();
            }
        };

        // Run the task in a background thread
        Thread backgroundThread = new Thread(task);
        // Terminate the running thread if the application exits
        backgroundThread.setDaemon(true);
        // Start the thread
        backgroundThread.start();
    }

    public void runTask() {
        for (int i = 1; i <= 10; i++) {
            try {
                board.add(pikachu, 5, 5);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void setPikachu(int r, int c) {
        board.add(pikachu, r, c);
        GridPane.setHalignment(pikachu, HPos.CENTER);
    }

}

1 Ответ

0 голосов
/ 13 ноября 2018

Я узнал, что GridPane не является поточно-ориентированным.

Не существует такого понятия, как поточно-ориентированное, когда дело доходит до узлов сцены JavaFX.Ожидается, что они будут изменены только из потока приложений JavaFX.

Я также пытался использовать Platform.runLater, но он все еще не работает.

Вам необходимопоместите это в правильной части также.Если бы вы сделали Platform.runLater(this::startTask);, то это ничего бы не сделало.

Вы должны использовать Platform.runLater(() -> board.....) для изменения графа сцены из потока приложений, отличного от JavaFX.

Наконец, вам действительно не следует использовать board.add().Многократное добавление элемента управления приведет к IllegalArgumentException, говорящему, что есть дублирующиеся дочерние элементы.

Так вот, что вы должны сделать:

Platform.runLater(() -> board.setConstraints(pikachu, 5, 5));

Я не уверен, почему выхотя всегда устанавливаем в строку 5 и столбец 5.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...