Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine clicked JPanel component in the MouseListener. Event handling

Tags:

java

swing

I have a class whitch extends 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");
    }

}

I have several instances of that class which is added to JFrame. I want to create one instanse of MouseAdapter class and then add them as a mouse listener to all of the ButtonPanel components on my JFrame. I meen:

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);

The MouseAdapterMod class I want to be separate from the other and locate in it's own package. It should looks like this:

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

So the problem is that I don't know how to implement mouseClicked method to make it determine which of ButtonPanel generate the event and call the corresponding to that component setButtonText() method. Is anyone know how to do that?

I know that I can achieve this by including event handling functionality in the ButtonPanel class, but thats not appropriate way for me, cuz I want to keep the class structure as I described above and have only one instance of MouseAdapterMod class for handling all of the ButtonPanels.

like image 866
Gubert Avatar asked Sep 07 '11 20:09

Gubert


1 Answers

The MouseEvent#getSource method will return which object has been clicked:

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();
   }
}

As the comments note, you're often better off listening for mousePressed or mouseReleased rather than mouseClicked because for mouseClicked to work, the press and release must be from the same point, and if the mouse shifts even a slight amount, the click won't register.

My test program:

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();
   }
}
like image 166
Hovercraft Full Of Eels Avatar answered Dec 13 '22 05:12

Hovercraft Full Of Eels