在MouseListener中确定所点击的JPanel组件。事件处理

6

我有一个扩展了JPanel的类:

public class ButtonPanel extends JPanel {

    private label;

    public ButtonPanel() {
        label=new JLabel("waiting for click");
        add(label);
    }

    public void setButtonText() {
        label.setText("just clicked");
    }

}

我有几个该类的实例,它们被添加到了JFrame上。我想创建一个MouseAdapter类的实例,并将其作为鼠标监听器添加到我JFrame上所有ButtonPanel组件中。我的意思是:

ButtonPanel butt1 = new ButtonPanel();
ButtonPanel butt2 = new ButtonPanel();
ButtonPanel butt3 = new ButtonPanel();
//... here goes code which add ButtonPanels to JFrame

MouseAdapterMod mam = new MouseAdapterMod();
butt1.addMouseListener(mam);
butt2.addMouseListener(mam);
butt3.addMouseListener(mam);

我希望将MouseAdapterMod类单独放在一个包中,与其他内容分开。它应该像这样:

public class MouseAdapterMod extends MouseAdapter {

    public void mouseClicked(MouseEvent e) {
        //here goes the code of calling setButtonText method of ButtonPanel component on which the event had occurred
    }
}

问题在于我不知道如何实现mouseClicked方法,以确定哪个ButtonPanel生成了事件并调用相应的组件setButtonText()方法。有人知道怎么做吗?

我知道可以通过在ButtonPanel类中包含事件处理功能来实现这一点,但对我来说并不合适,因为我希望保持上述描述的类结构,并仅有一个MouseAdapterMod类的实例来处理所有的ButtonPanels。


你最后一段写得很好,值得赞扬。 - Hovercraft Full Of Eels
1个回答

17

MouseEvent#getSource方法将返回被点击的对象:

public class MouseAdapterMod extends MouseAdapter {

   // usually better off with mousePressed rather than clicked
   public void mousePressed(MouseEvent e) {
       ButtonPanel btnPanel = (ButtonPanel)e.getSource();
       btnPanel.setButtonText();
   }
}

如评论所述,通常更好的方法是监听 mousePressed 或 mouseReleased 事件,而不是 mouseClicked,因为为了使 mouseClicked 起作用,必须从相同的点进行按下和释放,如果鼠标稍微移动一下,点击就无法注册。

我的测试程序:

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;

import javax.swing.*;

public class MainForButtonPanel extends JPanel {
   public MainForButtonPanel() {
      setLayout(new GridLayout(4, 4));

      MouseAdapter myMA = new MouseAdapterMod();

      for (int i = 0; i < 4; i++) {
         for (int j = 0; j < 4; j++) {
            ButtonPanel btnPanel = new ButtonPanel();
            btnPanel.addMouseListener(myMA);
            add(btnPanel);
         }
      }

   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("MainForButtonPanel");
      frame.getContentPane().add(new MainForButtonPanel());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

class ButtonPanel extends JPanel {

   private static final int TIMER_DELAY = 2000;
   private static final String JUST_CLICKED = "just clicked";
   private static final String WAITING_FOR_CLICK = "waiting for click";
   private static final Color CLICKED_COLOR = Color.pink;
   private JLabel label;

   public ButtonPanel() {
      label = new JLabel(WAITING_FOR_CLICK);
      add(label);
   }

   public void setButtonText() {
      label.setText(JUST_CLICKED);
      setBackground(CLICKED_COLOR);

      new Timer(TIMER_DELAY, new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            label.setText(WAITING_FOR_CLICK);
            setBackground(null);
            ((Timer)ae.getSource()).stop();
         }
      }).start();
   }

}

class MouseAdapterMod extends MouseAdapter {

   // usually better off with mousePressed rather than clicked
   public void mousePressed(MouseEvent e) {
       ButtonPanel btnPanel = (ButtonPanel)e.getSource();
       btnPanel.setButtonText();
   }
}

1
+1,当编写共享监听器时,getSource()再次拯救了我们。 - camickr
非常好的例子。我得到了比我要求的还要多。但是不确定setButtonText()方法中的Timer实例代表什么。抱歉..我是Java的新手;)..但无论如何,非常感谢您! - Gubert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接