回答編集履歴

5

修正

2024/02/15 17:37

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -149,7 +149,7 @@
149
149
  }
150
150
  });
151
151
  ```
152
- とすると、をクリックする度に label2 にも内/外と表示されるようになります。
152
+ とすると、 CirclePanel をクリックする度に label2 にも内/外と表示されるようになります。
153
153
 
154
154
  最後の「無名クラス」というのが慣れていないかもしれません。これを利用するとクラスを別途定義したり変数をフィールド化したりしなくても済む等で良く使われます。
155
155
  [Google検索: java swing 無名クラス](https://www.google.com/search?q=java+swing+%E7%84%A1%E5%90%8D%E3%82%AF%E3%83%A9%E3%82%B9)

4

追記

2024/02/15 06:25

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -154,3 +154,5 @@
154
154
  最後の「無名クラス」というのが慣れていないかもしれません。これを利用するとクラスを別途定義したり変数をフィールド化したりしなくても済む等で良く使われます。
155
155
  [Google検索: java swing 無名クラス](https://www.google.com/search?q=java+swing+%E7%84%A1%E5%90%8D%E3%82%AF%E3%83%A9%E3%82%B9)
156
156
  [Javaコード入門 TOP > 継承、インターフェイス > 無名クラスを定義する](https://bituse.info/java/27)
157
+
158
+ slider に設定している ChangeListener も無名クラスを利用すると label 等をフィールドにする必要が無くなったりします。

3

追加

2024/02/15 06:14

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -97,3 +97,60 @@
97
97
  }
98
98
  }
99
99
  ```
100
+ ---
101
+ 円のクリックで CirclePanel の外で何かしたい場合、例えばクリックが円の中なのか外なのかを label2 に表示するような場合は、 MouseListener のように「何かが起きたら特定のメソッドを呼んでくれる」構造を CirclePanel に作る感じにすると、 Swing の標準的なコンポーネントと似て(慣れている向きには)分かり易いです。
102
+ ちょっとコードが増えてきたので主に追加変更点のみの説明になりますが、 CirclePanel 内に interface を定義して、その型のフィールドと設定メソッドも作ります。(以下の 2~13 行目)
103
+ ```java
104
+ private static class CirclePanel extends JPanel {
105
+ interface CircleClickListener {
106
+ void onClick(TestFrame.CirclePanel circlePanel, boolean contains);
107
+ }
108
+ private CircleClickListener circleClickListener = null;
109
+
110
+ /**
111
+ * CircleClickListener を登録する
112
+ * @param listener
113
+ */
114
+ void setCircleClickListener(CircleClickListener listener) {
115
+ this.circleClickListener = listener;
116
+ }
117
+ ```
118
+ 回答で追加した EllipseClickListener クラスの mouseClicked メソッドの最後に、 circleClickListener が設定されていたら onClick メソッドを呼ぶ処理を追加します。(以下の 10 行目)
119
+ ```java
120
+ //円の範囲に反応するクラス
121
+ private class EllipseClickListener extends MouseAdapter {
122
+ @Override
123
+ public void mouseClicked(MouseEvent e) {
124
+ if(ellipse.contains(e.getPoint())) { //クリック位置が円に含まれるなら
125
+ System.out.println(e.getPoint() + "=図形内");
126
+ } else {
127
+ System.out.println(e.getPoint() + "=図形外");
128
+ }
129
+ if(circleClickListener != null) circleClickListener.onClick(CirclePanel.this, ellipse.contains(e.getPoint())); //リスナを実行
130
+ }
131
+ }
132
+ ```
133
+ これで CirclePanel 側は準備完了です。
134
+ 後は TestFrame のコンストラクタで label2 を定義している後辺りで (以下の 5~15 行目)
135
+ ```java
136
+ JLabel label2 = new JLabel("テスト");
137
+ label2.setBounds(300, 500, 100, 100);
138
+ add(label2);
139
+
140
+ //円がクリックされたら実行するものを設定
141
+ circlePanel.setCircleClickListener(new CirclePanel.CircleClickListener() { //無名クラスとして定義・設定
142
+ @Override
143
+ public void onClick(CirclePanel circlePanel, boolean contains) {
144
+ if(contains) {
145
+ label2.setText("内");
146
+ } else {
147
+ label2.setText("外");
148
+ }
149
+ }
150
+ });
151
+ ```
152
+ とすると、円をクリックする度に label2 にも内/外と表示されるようになります。
153
+
154
+ 最後の「無名クラス」というのが慣れていないかもしれません。これを利用するとクラスを別途定義したり変数をフィールド化したりしなくても済む等で良く使われます。
155
+ [Google検索: java swing 無名クラス](https://www.google.com/search?q=java+swing+%E7%84%A1%E5%90%8D%E3%82%AF%E3%83%A9%E3%82%B9)
156
+ [Javaコード入門 TOP > 継承、インターフェイス > 無名クラスを定義する](https://bituse.info/java/27)

2

言語名付け忘れ

2024/02/15 05:30

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -3,7 +3,7 @@
3
3
  最終的に図形クリック時にどのような動作をさせるのかによって作りを考える必要がありますが、取り合えず単に何か表示して確認する感じなら、円のクリック時の処理も CirclePanel に任せる形が簡単です。
4
4
 
5
5
  以下は MouseListener のアダプタ版である MouseAdapter を継承したクラスを CirclePanel 内で定義し、 paintComponent で作成した円とクリックされた座標を比較して標準出力に座標と図形内/外を表示しています。
6
- ```
6
+ ```java
7
7
  import java.awt.*;
8
8
  import java.awt.event.MouseAdapter;
9
9
  import java.awt.event.MouseEvent;

1

コード追加

2024/02/15 05:00

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -1 +1,99 @@
1
1
  MouseListener はコンポーネントに登録するものなので、その一部で反応させたいなら自分でクリックした座標から図形内かを調べてクリック時の動作をするかしないか判断する必要があります。
2
+
3
+ 最終的に図形クリック時にどのような動作をさせるのかによって作りを考える必要がありますが、取り合えず単に何か表示して確認する感じなら、円のクリック時の処理も CirclePanel に任せる形が簡単です。
4
+
5
+ 以下は MouseListener のアダプタ版である MouseAdapter を継承したクラスを CirclePanel 内で定義し、 paintComponent で作成した円とクリックされた座標を比較して標準出力に座標と図形内/外を表示しています。
6
+ ```
7
+ import java.awt.*;
8
+ import java.awt.event.MouseAdapter;
9
+ import java.awt.event.MouseEvent;
10
+ import java.awt.geom.Ellipse2D;
11
+
12
+ import javax.swing.*;
13
+ import javax.swing.event.ChangeEvent;
14
+ import javax.swing.event.ChangeListener;
15
+
16
+ public class TestFrame extends JFrame implements ChangeListener {
17
+ public static void main(String[] args) {
18
+ new TestFrame().setVisible(true);
19
+ }
20
+
21
+ private JSlider slider;
22
+ private JLabel label;
23
+ private CirclePanel circlePanel; //stateChanged メソッドで使うのでフィールド化
24
+
25
+ TestFrame() {
26
+ super("Swingサンプル(円の描画)");
27
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
28
+ setSize(800, 800);
29
+
30
+ circlePanel = new CirclePanel();
31
+
32
+ setContentPane(circlePanel);
33
+
34
+ label = new JLabel("test");
35
+ label.setBounds(300, 10, 100, 100);
36
+ add(label);
37
+
38
+ JLabel label2 = new JLabel("テスト");
39
+ label2.setBounds(300, 500, 100, 100);
40
+ add(label2);
41
+
42
+ slider = new JSlider(50, 150, 100); //最小値, 最大値, 初期値
43
+ slider.addChangeListener(this);
44
+ JPanel p = new JPanel();
45
+ p.add(slider);
46
+ p.setBounds(300, 300, 200, 50); //見易いようにちょっと大きく
47
+ add(p);
48
+ }
49
+
50
+ public void stateChanged(ChangeEvent e) {
51
+ label.setText("値:" + slider.getValue());
52
+ int value = slider.getValue();
53
+ circlePanel.setDiameter(value); //直径をスライダーの値に変更
54
+ }
55
+
56
+ private static class CirclePanel extends JPanel {
57
+ private final int X = 350, Y = 250; //円の中心
58
+ private int diameterOfCircle = 100; //円の直径
59
+ private Ellipse2D ellipse; //EllipseClickListener で使用する為にフィールド化
60
+
61
+ //円の範囲に反応するクラス
62
+ private class EllipseClickListener extends MouseAdapter {
63
+ @Override
64
+ public void mouseClicked(MouseEvent e) {
65
+ if(ellipse.contains(e.getPoint())) { //クリック位置が円に含まれるなら
66
+ System.out.println(e.getPoint() + "=図形内");
67
+ } else {
68
+ System.out.println(e.getPoint() + "=図形外");
69
+ }
70
+ }
71
+ }
72
+
73
+ CirclePanel() {
74
+ super(null); //レイアウトマネージャ無し
75
+ setBackground(Color.WHITE); //背景色
76
+ addMouseListener(new EllipseClickListener());
77
+ }
78
+
79
+ /**
80
+ * 円の直径を設定する
81
+ * @param diameter 直径 [px]
82
+ */
83
+ void setDiameter(int diameter) {
84
+ this.diameterOfCircle = diameter;
85
+ repaint(); //再描画依頼(後に Swing が paintComponent を呼んでくれる)
86
+ }
87
+
88
+ @Override
89
+ protected void paintComponent(Graphics g) {
90
+ super.paintComponent(g);
91
+
92
+ Graphics2D g2 = (Graphics2D) g;
93
+ g2.setColor(Color.BLUE);
94
+ ellipse = new Ellipse2D.Double(X - diameterOfCircle / 2, Y - diameterOfCircle / 2, diameterOfCircle, diameterOfCircle);
95
+ g2.fill(ellipse);
96
+ }
97
+ }
98
+ }
99
+ ```