下だけにリスナを登録すれば重なっている部分でも下が受け取ります。重なりの状態が変わるのなら、変わった時にリスナを付け替えることで出来るでしょう。
もしくは、各ラベルで受け取るのでは無くコンテナ(回答のコードでは MainPanel )が受け取って、 Z オーダーからラベルを決めて処理させるというテもあります。
もっとちゃんと(?)やるなら、 Swing のコンポーネント間でイベントがどう伝わっているのかを調べられると良いと思います。(分かり易い図を何処かで見た気がしたんですが見つかりませんでした。)
java
1import java.awt.Color;
2import java.awt.event.MouseAdapter;
3import java.awt.event.MouseEvent;
4
5import javax.swing.*;
6
7public class MainFrame extends JFrame {
8 public static void main(String[] args) {
9 SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true));
10 }
11
12 MainFrame() {
13 super("重なりイベント");
14 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
15
16 add(new MainPanel());
17
18 pack();
19 setLocationRelativeTo(null);
20 }
21
22 private static class MainPanel extends JPanel {
23 MainPanel() {
24 super(null);
25 setSize(320, 320);
26 setPreferredSize(getSize());
27 setBackground(Color.YELLOW);
28
29 addLabel("ABC", 20, 20, 200, 200, Color.GREEN, JLabel.TOP);
30
31 addLabel("123", 100, 100, 200, 200, Color.RED, JLabel.BOTTOM)
32 .addMouseListener(new LoggedMouseAdapter("123"));
33 }
34 private JLabel addLabel(String text, int x, int y, int w, int h, Color bg, int valign) {
35 JLabel label = new JLabel(text);
36 label.setBounds(x,y,w,h);
37 label.setOpaque(true);
38 label.setBackground(bg);
39 label.setVerticalAlignment(valign);
40 add(label);
41 return label;
42 }
43 }
44
45 private static class LoggedMouseAdapter extends MouseAdapter {
46 private String text;
47 LoggedMouseAdapter(String text) {
48 this.text = text;
49 }
50 @Override
51 public void mouseClicked(MouseEvent e) {
52 System.out.println(text + " clicked.");
53 }
54 @Override
55 public void mouseEntered(MouseEvent e) {
56 System.out.println(text + " entered.");
57 }
58 @Override
59 public void mouseExited(MouseEvent e) {
60 System.out.println(text + " existed.");
61 }
62 }
63}
123 entered.
123 existed.
123 entered.
123 clicked.
123 existed.
123 entered.
123 clicked.
123 existed.
ラベルの載っているパネルにマウスイベントを受信させて、その位置にある全ての子コンポーネントのメソッドを呼ぶようにするとこんな感じになります。
この場合、 MOUSE_ENTERED や MOUSE_EXITED は来ないのでそれが必要ならパネルが判断したりが必要になります。
java
1import java.awt.Color;
2import java.awt.Component;
3import java.awt.event.MouseEvent;
4
5import javax.swing.*;
6
7public class MainFrame extends JFrame {
8 public static void main(String[] args) {
9 SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true));
10 }
11
12 MainFrame() {
13 super("重なりイベント");
14 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
15
16 add(new MainPanel());
17
18 pack();
19 setLocationRelativeTo(null);
20 }
21
22 private static class MainPanel extends JPanel {
23 MainPanel() {
24 super(null);
25 setSize(320, 320);
26 setPreferredSize(getSize());
27 setBackground(Color.YELLOW);
28
29 add(new MyLabel("ABC", 20, 20, 200, 200, Color.GREEN, JLabel.TOP));
30 add(new MyLabel("123", 100, 100, 200, 200, Color.RED, JLabel.BOTTOM));
31
32 enableEvents(MouseEvent.MOUSE_EVENT_MASK | MouseEvent.MOUSE_MOTION_EVENT_MASK);
33 }
34
35 @Override
36 protected void processMouseEvent(MouseEvent e) {
37 Component[] components = getComponents();
38 for(Component c : components) {
39 if(c.getBounds().contains(e.getX(), e.getY()) && c instanceof MyLabel) {
40 ((MyLabel)c).receiveMouseEvent(SwingUtilities.convertMouseEvent(this, e, c));
41 }
42 }
43 }
44 @Override
45 protected void processMouseMotionEvent(MouseEvent e) {
46 processMouseEvent(e);
47 }
48 }
49
50 private static class MyLabel extends JLabel {
51 MyLabel(String text, int x, int y, int w, int h, Color bg, int valign) {
52 super(text);
53 setBounds(x,y,w,h);
54 setOpaque(true);
55 setBackground(bg);
56 setVerticalAlignment(valign);
57 }
58 //MouseListener 等の代わりになるメソッド
59 void receiveMouseEvent(MouseEvent e) {
60 System.out.println(getText() + " receive " + e);
61 }
62 }
63}
具体的なコードを提示されたので、改造する形で作ってみました。
また、フェードアウトが危険な構造だったため ScheduledExecutorService を用いるようにし、クリック位置に表示する矩形自体をフェードアウト処理をするオブジェクトとして扱っています。
なお、 paintComponent の中で count を減らすような "状態が変わる処理" をしてはいけません。
paintComponent はアプリコードから repaint() が呼ばれた時以外でも、例えばアプリのウインドウが一部隠されてから再び表示された時でも呼ばれますので、意図しないタイミングで状態が変わる可能性があります。
java
1import java.awt.*;
2import java.awt.event.MouseEvent;
3import java.util.ArrayList;
4import java.util.List;
5import java.util.concurrent.*;
6
7import javax.swing.*;
8
9public class TestFrame extends JFrame {
10 public static void main(String[] args) {
11 SwingUtilities.invokeLater(() -> new TestFrame().setVisible(true));
12 }
13
14 TestFrame() {
15 super("test");
16 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
17
18 add(new MainPanel());
19
20 pack();
21 setLocationRelativeTo(null);
22 }
23
24 private static class MainPanel extends JPanel {
25 MainPanel() {
26 super(null);
27 setSize(300, 200);
28 setPreferredSize(getSize());
29 setBackground(Color.GRAY);
30
31 add(new EffectLabel(0, 0, 300, 200));
32 add(new ClickLabel(90, 55, 100, 50));
33
34 enableEvents(MouseEvent.MOUSE_EVENT_MASK);
35 }
36
37 @Override
38 protected void processMouseEvent(MouseEvent e) {
39 Component[] components = getComponents();
40 for(Component c : components) {
41 if(c.getBounds().contains(e.getX(), e.getY()) && c instanceof MouseEventReceiver) {
42 ((MouseEventReceiver)c).receiveMouseEvent(SwingUtilities.convertMouseEvent(this, e, c));
43 }
44 }
45 }
46 }
47}
48
49interface MouseEventReceiver {
50 void receiveMouseEvent(MouseEvent e);
51}
52
53interface Shape {
54 void paint(Graphics g);
55}
56
57class EffectLabel extends JLabel implements MouseEventReceiver {
58 private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
59 private List<Shape> shapeList = new ArrayList<>();
60
61 private class FadeoutableSquare implements Runnable, Shape {
62 private static int SIZE = 20;
63 private int x, y, count;
64 private ScheduledFuture<?> future;
65
66 FadeoutableSquare(int x, int y) {
67 this.x = x - SIZE / 2;
68 this.y = y - SIZE / 2;
69 count = 255;
70 shapeList.add(this);
71 }
72 void setScheduledFuture(ScheduledFuture<?> future) {
73 this.future = future;
74 }
75 @Override
76 public void run() {
77 repaint();
78 SwingUtilities.invokeLater(() -> {
79 if(future == null) return;
80 if(count-- <= 0) {
81 future.cancel(false);
82 future = null;
83 shapeList.remove(this);
84 }
85 });
86 }
87 @Override
88 public void paint(Graphics g) {
89 g.setColor(new Color(255, 255, 255, count));
90 g.fillRect(x, y, SIZE, SIZE);
91 }
92 }
93
94 EffectLabel(int x, int y, int w, int h) {
95 super();
96 setBounds(x, y, w, h);
97 }
98
99 @Override
100 public void receiveMouseEvent(MouseEvent e) {
101 if(e.getID() == MouseEvent.MOUSE_CLICKED) {
102 FadeoutableSquare fs = new FadeoutableSquare(e.getX(), e.getY());
103 fs.setScheduledFuture(scheduler.scheduleAtFixedRate(fs, 1, 1, TimeUnit.MILLISECONDS));
104 }
105 }
106 @Override
107 protected void paintComponent(Graphics g) {
108 super.paintComponent(g);
109
110 for(Shape shape : shapeList) shape.paint(g);
111 }
112}
113
114class ClickLabel extends JLabel implements MouseEventReceiver {
115 ClickLabel(int x, int y, int w, int h) {
116 super();
117 setOpaque(true);
118 setBackground(Color.RED);
119 setBounds(x, y, w, h);
120 }
121
122 @Override
123 public void receiveMouseEvent(MouseEvent e) {
124 if(e.getID() == MouseEvent.MOUSE_CLICKED) System.out.println("Click!!");
125 }
126}