События в Java (слушатель) - PullRequest
0 голосов
/ 20 мая 2019

Я не первый раз спрашиваю об этом, но теперь я лучше знаю проблему.Итак, я хочу сделать настольную игру.У него есть стопка фишек, и за каждый ход игрок берет одну фишку из стека и добавляет ее на игровое поле, затем очередь следующего игрока и т. Д.

Плитки добавляются с помощью мышии отображаются в области сетки, которая находится внутри области прокрутки, которая находится внутри границы (потому что у нас будет больше вещей в боковых и, возможно, в верхней части).

Давайте проверим код:

public final class GUI extends Application {

    private Game _game;
    private GridPane _visualBoard;
    private Stage _primaryStage;

    @Override
    public void start(final Stage primaryStage) {
    //stuff
    play();
    primaryStage.show();
}


public static void main(String[] args) {
      Application.launch(args);
}

public void addTile(myTile r) {
      double x, y;
      myVisualTile vT = new myVisualTile(r)
      _visualBoard.setOnMousePressed(new EventHandler<MouseEvent>() {
           @Override
           public void handle(MouseEvent e) {
               double mouseX = e.getSceneX();
               double mouseY = e.getSceneY();
              _visualBoard.add(vT, x, y);
           }
      });
}

public void play() {
    Player j;
    int i = 0;
    while (!_tileStack.empty()) {
        if (i == _players.size()) i = 0;
        j = _players.get(i);
        i++;
        turn(j);
    }
    System.out.println("Final");
}

private void turn(Player j) {
    myTile r=_tileStack.poll();
    addTile(r);
}

Но на самом деле это работает не так, как должно.Зачем?Потому что на каком-то этапе мне нужно «прослушать» событие addTile (), поэтому я прочитал документацию об этом, но не получил однозначного ответа.

Кстати, позвольте мне указать, чтоЯ знаю, что плитки не будут добавлены в правильную строку сетки, столбец, так как я не знаю, как преобразовать пиксели в правильную позицию сетки, но это не главный вопрос.

Должен ли я использоватьEventListener или EventFilter?Какая разница между ними?Как их использовать?

1 Ответ

2 голосов
/ 20 мая 2019

Во-первых, я предлагаю прочитать этот учебник , чтобы узнать больше об обработке событий в JavaFX.


Исходя из этого и двух других вопросов, концептуальная проблема, с которой вы, похоже, сталкиваетесь, заключается в том, как создать «цикл без цикла».

Идея в том, что у вас будет класс, представляющий состояние игры. «Состояние» включает в себя такие вещи, как ход, какие плитки были размещены, какие плитки все еще доступны, какие ходы действительны, сколько очков имеет каждый человек, была ли игра выиграна и т. Д.

public class Game {

    private final Deque<Tile> tileStack = ...;
    private final Tile[][] board = ...; // where "null" would be open (might want a better data structure)
    private final List<Player> players = ...;
    private final Map<Player, Integer> points = ...;
    private int currentPlayerIndex;

    private Tile currentTile;

    // getters/setters (if necessary)...
}

При использовании шаблона проектирования, такого как MVVM, я полагаю, что выше будет ViewModel. И поскольку вы используете JavaFX, вы можете захотеть представить эти свойства как фактические экземпляры JavaFX [ReadOnly]Property. Таким образом, вы можете использовать привязку данных между View и ViewModel. Такие вещи, как Player и Tile будут объектами модели.

Тогда вы добавите методы к этому классу для управления состоянием игры.

public void tryPlaceTile(int row, int column) {
    if (isValidMove(row, column) {
        addPlacedTile(row, column); // might update points
        if (tileStack.isEmpty()) {
            currentTile = null;
            endGame(); // stops the game, determines winner
        } else {
            currentTile = tileStack.pop();
            currentPlayerIndex = currentPlayerIndex == players.size() - 1 ? 0 : currentPlayerIndex + 1;
            updateView(); // likely not needed with data binding
        }
    } else {
        notifyUserOfInvalidMove();
    }

    // let method simply return, it will be called again when
    // the (next) player clicks in the appropriate place of
    // the view
}

Теперь два приведенных выше фрагмента кода очень грубые (тем более что я не очень хорошо знаком с кодируемой вами игрой). Такие вещи, как updateView(), не обязательно будут необходимы при использовании привязки данных. isValidMove(int,int) и notifyUserOfInvalidMove() также не обязательно понадобятся, если только представление (в зависимости от состояния игры) не допускает взаимодействия с недопустимыми местоположениями. Но дело в том, что когда пользователь нажимает на местоположение, вы вызываете этот метод. Этот метод обрабатывает ход игрока и обновляет состояние игры . Изменение состояния должно влиять на вид, чтобы визуально точно отображалось состояние 1 . Как только метод возвращается, вы снова «ждете» следующего взаимодействия с пользователем.

node.setOnMouseClicked(event -> {
    gameInstance.tryPlaceTile(/* needed information */);
    // anything else that needs doing
});

1. Если вы в конечном итоге используете фоновые потоки, не забывайте обновлять представление (прямо или косвенно) только в потоке приложений JavaFX .


Я также рекомендую прочитать статьи и учебные пособия о:

  • Model-View-Controller (MVC)
  • Model-View-Presenter (MVP)
  • Модель-Вид-Вид-Модель (MVVM)

И их вариации. Эти архитектуры часто (не всегда) облегчают реализацию программного обеспечения, такого как приложения с графическим интерфейсом. Определите, какой из них лучше всего соответствует вашим потребностям (если есть), и используйте его.

...