简体   繁体   English

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

[英]How do I add a MouseListener to a graphics object inside another graphics object?

I'm working on a GUI for a card game and am using the ACM's student graphics library for the sake of familiarity. 我正在为纸牌游戏设计GUI,并且为了熟悉起见,正在使用ACM的学生图形库 I have written a program that draws my solitaire game to the screen, and am having trouble making it interactive. 我编写了一个程序,将我的单人纸牌游戏绘制到屏幕上,但无法使其具有交互性。

Background: 背景:

There are a lot of classes here, and I'll do my best to describe them each. 这里有很多类,我将尽力描述每个类。

  • Top level JFrame containing the application. 包含应用程序的顶级JFrame。
    • GCanvas (that holds all the graphics objects) GCanvas(包含所有图形对象)
      • SolitaireGameControl (GCompound holding all the other GCompounds making up the solitaire game) SolitaireGameControl(GCompound容纳组成纸牌游戏的所有其他GCompounds)
        • Array of PileViews, a pile of cards (GCompound consisting of an array of Cards) 一组PictureViews,一堆纸牌(由一组纸牌组成的GCompound)
          • Cards (GCompound consisting of rectangles and labels) 卡(由矩形和标签组成的GCompound)

( GCompound: a collection of graphics objects treated as one object. (If car was a GCompound, it would have GOval[] wheels, GRect body and so when I add it to the canvas, it displays as one object)) GCompound:被视为一个对象的图形对象的集合。(如果car是GCompound,它将具有GOval[] wheels, GRect body ,因此当我将其添加到画布中时,它将显示为一个对象))

A card as seen from the top-level class would look like a bit like this: jFrame.gCanvas.solitaireGameControl.pileViews[pile number].cardView 从顶级类中看到的卡片看起来像这样: jFrame.gCanvas.solitaireGameControl.pileViews[pile number].cardView

What I've been trying to do is add a MouseListener to every single card, so that when a card is clicked and a MouseEvent is fired, MouseEvent e.getSource() = the card that was clicked. 我一直想做的是向每张卡中添加一个MouseListener,以便在单击卡并触发MouseEvent时,MouseEvent e.getSource() =被单击的卡。

Here's how it looks now: 现在是这样的:

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.
}

问题图片

When I run this program, the source of every event is SolitaireGameControl, granted I leave in the this.addMouseListener(this); 当我运行该程序时,每个事件的源头都是SolitaireGameControl, this.addMouseListener(this);是我留在this.addMouseListener(this); . If I take out this statement, nothing is printed at all, leading me to believe that the mouseListeners I have added are only working one level deep. 如果我删除该语句,则什么都不会打印,这使我相信我添加的mouseListeners只能深入一层。 (The first GCompound on the canvas, not the GCompounds inside it.) (画布上的第一个GCompound,而不是其中的GCompounds。)

Therefore, my question is as follows: Is there a way to get a MouseListener for a GCompound inside of a GCompound inside of a GCompound, and have MouseEvent's getSource to correctly identify the card? 因此,我的问题如下:是否有办法在GCompound 内的 GCompound 获取GCompound的MouseListener,并使MouseEvent的getSource正确识别卡? If not, is there a way to restructure my program to make it work as intended? 如果没有,是否可以重组程序以使其按预期工作? (I know I should really be using a better graphics library for starters.) (我知道我确实应该为初学者使用更好的图形库。)

That would make sense. 那是有道理的。 From my experience, if I put some components inside a top-level container, the container is the one that receives input events. 根据我的经验,如果我将某些组件放在顶层容器中,则该容器就是接收输入事件的容器。

Have you tried an approach where you do something like: 您是否尝试过执行以下操作的方法:

/* 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);
            }
        }
    }
}

... and then handle mouse clicks on a 'CardView' level normally. ...然后正常处理“ CardView”级别的鼠标单击。

When the top-level container receives a mouse event, it checks if the mouse interacted with a card based on the location of the event (if the card's area contains the point). 当顶级容器收到鼠标事件时,它将根据事件的位置(如果卡的区域包含该点)检查鼠标是否与卡进行了交互。 If it did, it passes down the mouse event to the card's mouse listener. 如果是这样,它将鼠标事件传递给卡的鼠标侦听器。

I'm assuming that the elements near the beginning of 'pv.cardViews' are the cards that are more to the front. 我假设“ pv.cardViews”开头附近的元素是最靠前的卡片。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM