Как добавить MouseListener к графическому объекту внутри другого графического объекта? - PullRequest
2 голосов
/ 02 апреля 2012

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

Справочная информация:

Здесь много классов, и я сделаю все возможное, чтобы описать их каждый.

  • JFrame верхнего уровня, содержащий приложение.
    • GCanvas (который содержит все графические объекты)
      • SolitaireGameControl (GCompound содержит все остальные GCompounds, составляющие пасьянс)
        • Массив PileViews, куча карт (GCompound состоит из массива карт)
          • Карточки (G-соединение, состоящее из прямоугольников и меток)

( GCompound: коллекция графических объектов, обрабатываемых как один объект. (Если бы car был GCompound, он имел бы GOval[] wheels, GRect body, поэтому при добавлении его на холст он отображается как один объект))

Карта из класса верхнего уровня будет выглядеть примерно так: jFrame.gCanvas.solitaireGameControl.pileViews[pile number].cardView

То, что я пытался сделать, - это добавить MouseListener к каждой отдельной карте, чтобы при щелчке по карте и при запуске MouseEvent MouseEvent e.getSource() = карта, по которой щелкнули.

Вот как это выглядит сейчас:

public SolitaireGameControl(SolitaireGame game) {
    this.game = game; // Model of the game.
    this.pileViews = PileView.getPileViews(game.drawPiles); // ArrayList of PileViews (the pile of cards)

    for(PileView pv : pileViews) {
        for(CardView cv : pv.cardViews) {
            cv.addMouseListener(this); // add a mouseListener to the card
        }
    }

    this.addMouseListener(this); // if I don't include this, nothing happens when I click anything. If I do include this, this whole object is the source.
}

@Override
public void mouseClicked(MouseEvent e) {
    System.out.println(e.getSource()); // should return the card I clicked.
}

Picture of the problem

Когда я запускаю эту программу, источником каждого события является SolitaireGameControl, если оставить в this.addMouseListener(this);. Если я вычеркну это утверждение, то ничего не будет напечатано, что заставит меня поверить, что добавленные мной мышиные прослушиватели работают только на один уровень. (Первый GCompound на холсте, а не GCompounds внутри него.)

Поэтому мой вопрос заключается в следующем: есть ли способ получить MouseListener для GCompound внутри GCompound внутри GCompound и иметь MouseSvent getSource для правильной идентификации карта? Если нет, то есть ли способ реструктурировать мою программу, чтобы она работала как задумано? (Я знаю, что я действительно должен использовать лучшую графическую библиотеку для начинающих.)

1 Ответ

1 голос
/ 02 апреля 2012

Это имело бы смысл.Исходя из моего опыта, если я помещу некоторые компоненты в контейнер верхнего уровня, это контейнер, который получает входные события.

Вы пробовали подход, когда вы делаете что-то вроде:

/* This is the mouse listener for the top-level container. */
@Override
public void mouseClicked(MouseEvent e) {
    for(PileView pv : pileViews) {
        for(CardView cv : pv.cardViews) {
            if(cv.getBounds().contains(e.getPoint())) {
                cv.dispatchEvent(e);
            }
        }
    }
}

... и затем обрабатывать щелчки мыши на уровне «CardView» в обычном режиме.

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

Я предполагаю, что элементы в начале 'pv.cardViews' - это карты, находящиеся ближе к передней части.

...