回答編集履歴
4
追記
test
CHANGED
@@ -152,6 +152,8 @@
|
|
152
152
|
|
153
153
|
具体的なコードを提示されたので、改造する形で作ってみました。
|
154
154
|
また、フェードアウトが危険な構造だったため ScheduledExecutorService を用いるようにし、クリック位置に表示する矩形自体をフェードアウト処理をするオブジェクトとして扱っています。
|
155
|
+
なお、 paintComponent の中で count を減らすような "状態が変わる処理" をしてはいけません。
|
156
|
+
paintComponent はアプリコードから repaint() が呼ばれた時以外でも、例えばアプリのウインドウが一部隠されてから再び表示された時でも呼ばれますので、意図しないタイミングで状態が変わる可能性があります。
|
155
157
|
```java
|
156
158
|
import java.awt.*;
|
157
159
|
import java.awt.event.MouseEvent;
|
3
サンプルを改造する形のコードを追加
test
CHANGED
@@ -147,3 +147,136 @@
|
|
147
147
|
}
|
148
148
|
}
|
149
149
|
```
|
150
|
+
|
151
|
+
---
|
152
|
+
|
153
|
+
具体的なコードを提示されたので、改造する形で作ってみました。
|
154
|
+
また、フェードアウトが危険な構造だったため ScheduledExecutorService を用いるようにし、クリック位置に表示する矩形自体をフェードアウト処理をするオブジェクトとして扱っています。
|
155
|
+
```java
|
156
|
+
import java.awt.*;
|
157
|
+
import java.awt.event.MouseEvent;
|
158
|
+
import java.util.ArrayList;
|
159
|
+
import java.util.List;
|
160
|
+
import java.util.concurrent.*;
|
161
|
+
|
162
|
+
import javax.swing.*;
|
163
|
+
|
164
|
+
public class TestFrame extends JFrame {
|
165
|
+
public static void main(String[] args) {
|
166
|
+
SwingUtilities.invokeLater(() -> new TestFrame().setVisible(true));
|
167
|
+
}
|
168
|
+
|
169
|
+
TestFrame() {
|
170
|
+
super("test");
|
171
|
+
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
172
|
+
|
173
|
+
add(new MainPanel());
|
174
|
+
|
175
|
+
pack();
|
176
|
+
setLocationRelativeTo(null);
|
177
|
+
}
|
178
|
+
|
179
|
+
private static class MainPanel extends JPanel {
|
180
|
+
MainPanel() {
|
181
|
+
super(null);
|
182
|
+
setSize(300, 200);
|
183
|
+
setPreferredSize(getSize());
|
184
|
+
setBackground(Color.GRAY);
|
185
|
+
|
186
|
+
add(new EffectLabel(0, 0, 300, 200));
|
187
|
+
add(new ClickLabel(90, 55, 100, 50));
|
188
|
+
|
189
|
+
enableEvents(MouseEvent.MOUSE_EVENT_MASK);
|
190
|
+
}
|
191
|
+
|
192
|
+
@Override
|
193
|
+
protected void processMouseEvent(MouseEvent e) {
|
194
|
+
Component[] components = getComponents();
|
195
|
+
for(Component c : components) {
|
196
|
+
if(c.getBounds().contains(e.getX(), e.getY()) && c instanceof MouseEventReceiver) {
|
197
|
+
((MouseEventReceiver)c).receiveMouseEvent(SwingUtilities.convertMouseEvent(this, e, c));
|
198
|
+
}
|
199
|
+
}
|
200
|
+
}
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
interface MouseEventReceiver {
|
205
|
+
void receiveMouseEvent(MouseEvent e);
|
206
|
+
}
|
207
|
+
|
208
|
+
interface Shape {
|
209
|
+
void paint(Graphics g);
|
210
|
+
}
|
211
|
+
|
212
|
+
class EffectLabel extends JLabel implements MouseEventReceiver {
|
213
|
+
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
|
214
|
+
private List<Shape> shapeList = new ArrayList<>();
|
215
|
+
|
216
|
+
private class FadeoutableSquare implements Runnable, Shape {
|
217
|
+
private static int SIZE = 20;
|
218
|
+
private int x, y, count;
|
219
|
+
private ScheduledFuture<?> future;
|
220
|
+
|
221
|
+
FadeoutableSquare(int x, int y) {
|
222
|
+
this.x = x - SIZE / 2;
|
223
|
+
this.y = y - SIZE / 2;
|
224
|
+
count = 255;
|
225
|
+
shapeList.add(this);
|
226
|
+
}
|
227
|
+
void setScheduledFuture(ScheduledFuture<?> future) {
|
228
|
+
this.future = future;
|
229
|
+
}
|
230
|
+
@Override
|
231
|
+
public void run() {
|
232
|
+
repaint();
|
233
|
+
SwingUtilities.invokeLater(() -> {
|
234
|
+
if(future == null) return;
|
235
|
+
if(count-- <= 0) {
|
236
|
+
future.cancel(false);
|
237
|
+
future = null;
|
238
|
+
shapeList.remove(this);
|
239
|
+
}
|
240
|
+
});
|
241
|
+
}
|
242
|
+
@Override
|
243
|
+
public void paint(Graphics g) {
|
244
|
+
g.setColor(new Color(255, 255, 255, count));
|
245
|
+
g.fillRect(x, y, SIZE, SIZE);
|
246
|
+
}
|
247
|
+
}
|
248
|
+
|
249
|
+
EffectLabel(int x, int y, int w, int h) {
|
250
|
+
super();
|
251
|
+
setBounds(x, y, w, h);
|
252
|
+
}
|
253
|
+
|
254
|
+
@Override
|
255
|
+
public void receiveMouseEvent(MouseEvent e) {
|
256
|
+
if(e.getID() == MouseEvent.MOUSE_CLICKED) {
|
257
|
+
FadeoutableSquare fs = new FadeoutableSquare(e.getX(), e.getY());
|
258
|
+
fs.setScheduledFuture(scheduler.scheduleAtFixedRate(fs, 1, 1, TimeUnit.MILLISECONDS));
|
259
|
+
}
|
260
|
+
}
|
261
|
+
@Override
|
262
|
+
protected void paintComponent(Graphics g) {
|
263
|
+
super.paintComponent(g);
|
264
|
+
|
265
|
+
for(Shape shape : shapeList) shape.paint(g);
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
269
|
+
class ClickLabel extends JLabel implements MouseEventReceiver {
|
270
|
+
ClickLabel(int x, int y, int w, int h) {
|
271
|
+
super();
|
272
|
+
setOpaque(true);
|
273
|
+
setBackground(Color.RED);
|
274
|
+
setBounds(x, y, w, h);
|
275
|
+
}
|
276
|
+
|
277
|
+
@Override
|
278
|
+
public void receiveMouseEvent(MouseEvent e) {
|
279
|
+
if(e.getID() == MouseEvent.MOUSE_CLICKED) System.out.println("Click!!");
|
280
|
+
}
|
281
|
+
}
|
282
|
+
```
|
2
追加
test
CHANGED
@@ -78,3 +78,72 @@
|
|
78
78
|
123 clicked.
|
79
79
|
123 existed.
|
80
80
|
```
|
81
|
+
---
|
82
|
+
|
83
|
+
ラベルの載っているパネルにマウスイベントを受信させて、その位置にある全ての子コンポーネントのメソッドを呼ぶようにするとこんな感じになります。
|
84
|
+
この場合、 MOUSE_ENTERED や MOUSE_EXITED は来ないのでそれが必要ならパネルが判断したりが必要になります。
|
85
|
+
```java
|
86
|
+
import java.awt.Color;
|
87
|
+
import java.awt.Component;
|
88
|
+
import java.awt.event.MouseEvent;
|
89
|
+
|
90
|
+
import javax.swing.*;
|
91
|
+
|
92
|
+
public class MainFrame extends JFrame {
|
93
|
+
public static void main(String[] args) {
|
94
|
+
SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true));
|
95
|
+
}
|
96
|
+
|
97
|
+
MainFrame() {
|
98
|
+
super("重なりイベント");
|
99
|
+
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
100
|
+
|
101
|
+
add(new MainPanel());
|
102
|
+
|
103
|
+
pack();
|
104
|
+
setLocationRelativeTo(null);
|
105
|
+
}
|
106
|
+
|
107
|
+
private static class MainPanel extends JPanel {
|
108
|
+
MainPanel() {
|
109
|
+
super(null);
|
110
|
+
setSize(320, 320);
|
111
|
+
setPreferredSize(getSize());
|
112
|
+
setBackground(Color.YELLOW);
|
113
|
+
|
114
|
+
add(new MyLabel("ABC", 20, 20, 200, 200, Color.GREEN, JLabel.TOP));
|
115
|
+
add(new MyLabel("123", 100, 100, 200, 200, Color.RED, JLabel.BOTTOM));
|
116
|
+
|
117
|
+
enableEvents(MouseEvent.MOUSE_EVENT_MASK | MouseEvent.MOUSE_MOTION_EVENT_MASK);
|
118
|
+
}
|
119
|
+
|
120
|
+
@Override
|
121
|
+
protected void processMouseEvent(MouseEvent e) {
|
122
|
+
Component[] components = getComponents();
|
123
|
+
for(Component c : components) {
|
124
|
+
if(c.getBounds().contains(e.getX(), e.getY()) && c instanceof MyLabel) {
|
125
|
+
((MyLabel)c).receiveMouseEvent(SwingUtilities.convertMouseEvent(this, e, c));
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
129
|
+
@Override
|
130
|
+
protected void processMouseMotionEvent(MouseEvent e) {
|
131
|
+
processMouseEvent(e);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
private static class MyLabel extends JLabel {
|
136
|
+
MyLabel(String text, int x, int y, int w, int h, Color bg, int valign) {
|
137
|
+
super(text);
|
138
|
+
setBounds(x,y,w,h);
|
139
|
+
setOpaque(true);
|
140
|
+
setBackground(bg);
|
141
|
+
setVerticalAlignment(valign);
|
142
|
+
}
|
143
|
+
//MouseListener 等の代わりになるメソッド
|
144
|
+
void receiveMouseEvent(MouseEvent e) {
|
145
|
+
System.out.println(getText() + " receive " + e);
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
```
|
1
追記
test
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
下だけにリスナを登録すれば重なっている部分でも下が受け取ります。
|
2
|
-
重なりの状態が変わるのなら、変わった時にリスナを付け替えることで出来るでしょう。
|
1
|
+
下だけにリスナを登録すれば重なっている部分でも下が受け取ります。重なりの状態が変わるのなら、変わった時にリスナを付け替えることで出来るでしょう。
|
2
|
+
もしくは、各ラベルで受け取るのでは無くコンテナ(回答のコードでは MainPanel )が受け取って、 Z オーダーからラベルを決めて処理させるというテもあります。
|
3
|
+
|
3
4
|
もっとちゃんと(?)やるなら、 Swing のコンポーネント間でイベントがどう伝わっているのかを調べられると良いと思います。(分かり易い図を何処かで見た気がしたんですが見つかりませんでした。)
|
4
5
|
```java
|
5
6
|
import java.awt.Color;
|