如何将MouseListener添加到另一个图形对象内的图形对象?

时间:2012-04-01 21:10:25

标签: java graphics mouselistener

我正在开发一个用于纸牌游戏的GUI,并且为了熟悉而使用ACM's student graphics library。我写了一个程序,将我的单人纸牌游戏吸引到屏幕上,并且无法使其成为互动游戏。

背景

这里有很多课程,我会尽力对它们进行描述。

  • 包含应用程序的顶级JFrame。
    • GCanvas(包含所有图形对象)
      • SolitaireGameControl(GCompound持有所有其他GCompound构成单人纸牌游戏)
        • PileViews数组,一堆卡片(由一系列卡组成的GCompound)
          • 卡片(GCompound由矩形和标签组成)

GCompound:一个被视为一个对象的图形对象集合。(如果car是一个GCompound,它会有GOval[] wheels, GRect body,所以当我将它添加到canvas,它显示为一个对象))

从顶级课程中看到的卡片看起来有点像这样: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);。如果我拿出这个声明,根本没有打印任何内容,这让我相信我添加的mouseListeners只能在一个深度上工作。 (画布上的第一个GCompound,而不是其中的GCompound。)

因此,我的问题如下:是否有办法在 GCompound中的 GCompound 内部获取GCompound 的MouseListener,并将MouseEvent的getSource设置为正确识别卡?如果没有,有没有办法重组我的程序,使其按预期工作? (我知道我应该为初学者使用更好的图形库。)

1 个答案:

答案 0 :(得分:1)

这是有道理的。根据我的经验,如果我将一些组件放在顶级容器中,那么容器就是接收输入事件的容器。

您是否尝试过以下方法:

/* 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'开头附近的元素是前面的卡片。