Java JPanel上的mouseListener出现问题

Java JPanel上的mouseListener出现问题,java,mouse,listener,Java,Mouse,Listener,我对JPanel中的mouseListener有问题。 我在JPanel上添加了包含图像(大小为600 x 600)的JLabel,并为JPanel添加了mouseListener 每次我点击图像时,图像都会变成另一个图像,这很好。但是,问题是,只有单击图像的右侧或中心,图像才会更改为另一个图像。当我点击顶部或左侧时,图像不会改变。这让我很困惑。我希望在单击图像显示中的任意位置时,图像会更改为另一个图像 private final int SECOND= 1; private final int

我对JPanel中的mouseListener有问题。 我在JPanel上添加了包含图像(大小为600 x 600)的JLabel,并为JPanel添加了mouseListener

每次我点击图像时,图像都会变成另一个图像,这很好。但是,问题是,只有单击图像的右侧或中心,图像才会更改为另一个图像。当我点击顶部或左侧时,图像不会改变。这让我很困惑。我希望在单击图像显示中的任意位置时,图像会更改为另一个图像

private final int SECOND= 1;
private final int FIRST = 0;
int imageCounter = 0;

JLabel picture;
JPanel panel;

...

private mainLayout () {
  GridBagLayout m = new GridBagLayout();
  Container c = (Container)getContentPane();
  GridBagConstraints con;
  c.setLayout (m);

  picture = new JLabel();
  picture.setIcon(getImages(myImage.get(imageCounter).get(FIRST)));  //first Image

  panel = new JPanel();     
  con = new GridBagConstraints();
  con.anchor=GridBagConstraints.CENTER;
  con.gridy = 1; con.gridx = 0;     
  m.setConstraints(panel, con);
  c.add(panel);
  panel.add(picture); //add the pictures

  panel.addMouseListener(l);
  ....
}

MouseListener l = new MouseAdapter(){
  public void mouseClicked (MouseEvent e) 
  {
    Point p = e.getPoint();
    if((panel.getBounds().contains(p))
       picture.setIcon(getImages(myImage.get(imageCounter).get(SECOND)));
  }
};

你确定你真的在点击吗?只有在完全相同的位置按下和释放鼠标时,才会触发鼠标单击事件。如果您在单击时鼠标移动得很小,则不会触发事件。

您确定您确实在单击吗?只有在完全相同的位置按下和释放鼠标时,才会触发鼠标单击事件。如果鼠标在单击时移动得很小,则不会触发事件。

出于好奇,为什么要使用JLabel显示图像?您最好编写一个ImagePanel类来扩展JPanel并重写paint()方法来绘制自己的图形。然后,您可以将鼠标听筒直接连接到面板上。

出于好奇,您为什么要使用JLabel显示图像?您最好编写一个ImagePanel类来扩展JPanel并重写paint()方法来绘制自己的图形。然后,您可以将鼠标侦听器直接连接到面板。

问题似乎出现在以下不必要的代码中:

Point p = e.getPoint();
if((panel.getBounds().contains(p))
鼠标侦听器位于面板上,因此鼠标坐标将相对于面板左上角
panel.getBounds()
获取面板相对于其父容器的边界


值得注意的是,鼠标事件的行为非常奇怪。它们会“冒泡”,直到碰到连接了鼠标侦听器的组件。因此,添加鼠标侦听器实际上会改变组件的行为。将侦听器添加到父级可能会错过事件,具体取决于组件的确切设置方式(可能会任意更改)。解决这个问题的方法有很多,但没有一种是好的。

问题似乎就在这段不必要的代码中:

Point p = e.getPoint();
if((panel.getBounds().contains(p))
鼠标侦听器位于面板上,因此鼠标坐标将相对于面板左上角
panel.getBounds()
获取面板相对于其父容器的边界


值得注意的是,鼠标事件的行为非常奇怪。它们会“冒泡”,直到碰到连接了鼠标侦听器的组件。因此,添加鼠标侦听器实际上会改变组件的行为。将侦听器添加到父级可能会错过事件,具体取决于组件的确切设置方式(可能会任意更改)。有很多方法可以解决这个问题,但没有一种是好的。

您可能遇到的问题与我遇到的相同,即您的事件在您的层次结构中被吞噬,正如前面的海报所暗示的那样。关于中工国际商用飞机有限公司的回复,只要您知道后果,您是否扩展
JPanel
JLabel
,其实并不重要
JPanel
为您提供了更多的功能,并且已经内置了许多有用的东西。但让我们举一个简单的例子,你有以下几点:

包含
JPanel
JFrame
,称之为
JParent
JParent
有一组专用的鼠标侦听器

JParent
包含添加到其组件中的子
JPanel
,名为
JChild
JChild
也有自己的一组鼠标侦听器

单击未被
JChild
占用的区域时发生了什么?您将得到
JParent
的侦听器的响应。如果在
JChild
可见的区域中单击,则只有
JChild
的鼠标事件才会触发

因此,在调试时要非常小心,因为Java的swing可能具有不同于其他绘制简单表单/GUI实现的行为。事件基本上是一次性的,最低级别的组件获得第一个DIB。如果仍然尝试触发父事件,则x/y坐标将基于子事件而不是父事件。我仍在努力为自己找到一个好的解决方案,因为我需要专门访问父对象以将对象移动到其他位置

我能想到的最好的方法是调试/思考以下两个想法: a) 让每个组件都包含自己独有的事件集,并尝试防止“冒泡”效应发挥作用。 b) 处理父级上的所有事件

我更喜欢a,因为它避免了令人讨厌的事情,比如检查组件类只是为了弄清楚您想要什么样的反应(例如,显示什么样的右键单击菜单)


编辑:所以你可以用我发现的任何一种方法来处理这个问题。您可以使用dispatchEvent消息将事件转发回链的上游。在我的例子中,我必须吞噬第一个事件(或改变它),并发送x-y位置,就好像它们相对于父事件一样(使用偏移量)。我认为更好的方法是通过转发,因为这样可以封装您的所有单个组件。

您可能遇到的问题与我遇到的问题相同,即您的事件在您的层次结构中被吞噬,正如前面的海报所暗示的。关于中工国际商用飞机有限公司的回复,只要您知道后果,您是否扩展
JPanel
JLabel
,其实并不重要
JPanel
为您提供了更多的功能,并且已经内置了许多有用的东西。但让我们举一个简单的例子,你有以下几点:

包含以下内容的
JFrame