質問するログイン新規登録

回答編集履歴

1

返信が想像どおりだったので模範回答を追記

2015/12/19 18:08

投稿

ipadcaron
ipadcaron

スコア1693

answer CHANGED
@@ -1,2 +1,313 @@
1
1
  レイアウトマネージャーの問題かな。
2
- gridbaglayout とか使えばいいんじゃないでしょか。
2
+ gridbaglayout とか使えばいいんじゃないでしょか。
3
+
4
+ ![イメージ説明](05770cbfd8bc20dc5134a45d439f4abf.png)
5
+
6
+ ![イメージ説明](7de95ce16359ffdbb210137877064bfb.png)
7
+
8
+ 模範回答?作ったのでコピペで実行確認してみてください。
9
+
10
+ 変な書き方でかいてありますが、ちゃんとあなたの希望通りです。
11
+
12
+ 動作環境:Mac, Eclipse Luna Java1.8 swing
13
+
14
+ Debtaku.java で保存
15
+ ```java
16
+ package jp.kanagawa.caron.swing.tools;
17
+
18
+ import java.awt.BorderLayout;
19
+ import java.awt.event.ActionEvent;
20
+ import java.awt.event.ActionListener;
21
+ import java.util.HashMap;
22
+ import java.util.Map;
23
+
24
+ import javax.script.ScriptEngine;
25
+ import javax.script.ScriptEngineManager;
26
+ import javax.swing.JButton;
27
+ import javax.swing.JFrame;
28
+ import javax.swing.JPanel;
29
+
30
+ /**
31
+ * swing で電卓、普通の四則演算ができる電卓を作ります。
32
+ * MC,C, ,
33
+ * (,),+,-
34
+ * 1,2,3,/
35
+ * 4,5,6,*
36
+ * 7,8,9,%
37
+ * =,0,$,_
38
+ * ( 左かっこ
39
+ * ) 右かっこ
40
+ * MC = Memory Clear
41
+ * C = Clear
42
+ * 0-9 Number
43
+ * + prefix / add
44
+ * - prefix / sub
45
+ * "/" div
46
+ * "%" mod
47
+ * "*" mul
48
+ * "$" register $0-$7 まで。
49
+ *
50
+ * 計算部分は、ScriptEngine による大幅な手抜き動作です。
51
+ * 最近はやりの 3 * 1/3 + 1 が 10になるってのも Javascript なら正しい結果になります。
52
+ *
53
+ * @author masa01
54
+ *
55
+ */
56
+ public class Dentaku extends JFrame {
57
+
58
+ /**
59
+ *
60
+ */
61
+ private static final long serialVersionUID = 1L;
62
+
63
+ public static void main(String...args) {
64
+
65
+ new Dentaku();
66
+
67
+ }
68
+
69
+ private ScriptEngine engine;
70
+
71
+ private Map<String, Object> paramMap;
72
+
73
+ private StringBuilder buffer;
74
+
75
+ public Dentaku() {
76
+ // JavaScript Engine nathhorn を取得
77
+ engine = new ScriptEngineManager().getEngineByName("JavaScript");
78
+ paramMap = new HashMap<String, Object>();
79
+ buffer = new StringBuilder(500);
80
+
81
+ init();
82
+
83
+ initLayout();
84
+
85
+ super.setDefaultCloseOperation(EXIT_ON_CLOSE);
86
+
87
+ super.setSize(400, 400);
88
+
89
+ super.setVisible(true);
90
+
91
+ }
92
+ private void init() {
93
+ // 電卓計算結果の途中保存用レジスタの登録と初期化
94
+ paramMap.put("$0", null);
95
+ paramMap.put("$1", null);
96
+ paramMap.put("$2", null);
97
+ paramMap.put("$3", null);
98
+ paramMap.put("$4", null);
99
+ paramMap.put("$5", null);
100
+ paramMap.put("$6", null);
101
+ paramMap.put("$7", null);
102
+
103
+ //$err エラーメッセージ格納用変数を定義する
104
+ paramMap.put("$err", null);
105
+
106
+ // レジスタを使わない計算の結果はすべてここに入る
107
+ paramMap.put("$ans", null);
108
+
109
+ // バッファクリア
110
+ buffer.setLength(0);
111
+ }
112
+
113
+ /**
114
+ * try { sys.$ans = ("画面で入力した羅列"); } catch (e) { sys.$err = e; }
115
+ * を作ります。ScriptEngine の eval を実行すると結果が java から取得できるっていう感じですね。
116
+ * @return
117
+ */
118
+ private String createJs() {
119
+ return null;
120
+ }
121
+
122
+ /**
123
+ * 画面レイアウトを変更するならオーバーライドしてください。
124
+ * デフォルトでは、
125
+ * BorderLayout で、
126
+ * North : 計算入力用テキストフィールド(直接入力不可)、readonly
127
+ * Center: 数字と記号とその他パーツを 4 * 4 のマトリクスにしたもの
128
+ * South : 実行結果の履歴
129
+ *
130
+ */
131
+ protected void initLayout() {
132
+
133
+ ActionListener be = new ActionListener() {
134
+
135
+ @Override
136
+ public void actionPerformed(ActionEvent e) {
137
+
138
+ System.out.println(e.getActionCommand());
139
+ }
140
+ };
141
+
142
+ JPanel gp = new GridLayoutPanel(6, 4)
143
+ .add(0, 0, createButton("MC", "MC", "MC", be))
144
+ .add(0, 1, createButton("C", "C", "C", be))
145
+ .add(0, 2, createButton(" ", " ", "NOP", be))
146
+ .add(0, 3, createButton(" ", " ", "NOP", be))
147
+
148
+ .add(1, 0, createButton("LPAR", "(", "LPAR", be))
149
+ .add(1, 1, createButton("RPAR", ")", "RPAR", be))
150
+ .add(1, 2, createButton("ADD", "+", "ADD", be))
151
+ .add(1, 3, createButton("SUB", "-", "SUB", be))
152
+
153
+ .add(2, 0, createButton("ONE", "1", "ONE", be))
154
+ .add(2, 1, createButton("TWO", "2", "TWO", be))
155
+ .add(2, 2, createButton("TRE", "3", "TRE", be))
156
+ .add(2, 3, createButton("DIV", "/", "DIV", be))
157
+
158
+ .add(3, 0, createButton("FOR", "4", "FOR", be))
159
+ .add(3, 1, createButton("FIV", "5", "FIV", be))
160
+ .add(3, 2, createButton("SIX", "6", "SIX", be))
161
+ .add(3, 3, createButton("MUL", "*", "MUL", be))
162
+
163
+ .add(4, 0, createButton("SVN", "4", "SVN", be))
164
+ .add(4, 1, createButton("EGT", "5", "EGT", be))
165
+ .add(4, 2, createButton("NIN", "9", "NIN", be))
166
+ .add(4, 3, createButton("MOD", "%", "MOD", be))
167
+
168
+ .add(5, 0, createButton("EQU", "=", "EQU", be))
169
+ .add(5, 1, createButton("ZRO", "0", "ZRO", be))
170
+ .add(5, 2, createButton("DOL", "$", "DOL", be))
171
+ .add(5, 3, createButton("USC", "_", "USC", be))
172
+
173
+ .done();
174
+ /*
175
+ * MC,C, ,
176
+ * (,),+,-
177
+ * 1,2,3,/
178
+ * 4,5,6,*
179
+ * 7,8,9,%
180
+ * =,0,$,_
181
+ */
182
+
183
+ super.getContentPane().add(gp, BorderLayout.CENTER);
184
+
185
+ }
186
+ /**
187
+ * ボタンを作る、アイコンボタンにしたいならオーバーライドする
188
+ * @param name
189
+ * @param text
190
+ * @param command
191
+ * @return
192
+ */
193
+ protected JButton createButton(String name, String text, String command, ActionListener actionListener) {
194
+ JButton jb = new JButton(text);
195
+ // アクションコマンド設定、集約イベントハンドラ内でこのコマンドを取得して対応アクションで処理する
196
+ jb.setActionCommand(command);
197
+ // 名前を設定
198
+ jb.setName(name);
199
+ // 集約?イベントを設定する
200
+ jb.addActionListener(actionListener);
201
+ return jb;
202
+ }
203
+
204
+ /**
205
+ * @author masa01
206
+ *
207
+ */
208
+
209
+ }
210
+
211
+ ```
212
+
213
+ GridLayoutPanel.java で保存
214
+ ```java
215
+ package jp.kanagawa.caron.swing.tools;
216
+
217
+ import java.awt.Component;
218
+ import java.awt.GridLayout;
219
+ import java.util.ArrayList;
220
+ import java.util.Comparator;
221
+ import java.util.List;
222
+
223
+ import javax.swing.JPanel;
224
+
225
+ public class GridLayoutPanel extends GridLayout {
226
+
227
+ /**
228
+ *
229
+ */
230
+ private static final long serialVersionUID = 1L;
231
+
232
+ private List<Compo> comps;
233
+ private int rows, cols;
234
+
235
+ class Compo {
236
+ int x, y;
237
+ int val;
238
+ Component compo;
239
+ public Compo(int x, int y, Component compo) {
240
+ this.x = x;
241
+ this.y = y;
242
+ this.compo = compo;
243
+ this.val = (x + 1) * (y + 1);
244
+ }
245
+ }
246
+
247
+ public GridLayoutPanel(int row, int col) {
248
+ super(row, col);
249
+
250
+ rows = row;
251
+ cols = col;
252
+ comps = new ArrayList<Compo>();
253
+ }
254
+
255
+ public GridLayoutPanel add(int row, int col, Component comp) {
256
+
257
+ Utils.assertRange(row, 0, rows);
258
+ Utils.assertRange(col, 0, cols);
259
+ Utils.assertNull(comp);
260
+
261
+ comps.add(new Compo(col, row, comp));
262
+ return this;
263
+ }
264
+ public JPanel done() {
265
+ comps.sort(new Comparator<Compo>() {
266
+ @Override
267
+ public int compare(Compo o1, Compo o2) {
268
+ // o1 - o2 は昇順ソート
269
+ // o2 - o1 は降順ソート
270
+ int v1 = o1.y * rows + o1.x;
271
+ int v2 = o2.y * rows + o2.x;
272
+
273
+ return v1 - v2;
274
+
275
+
276
+ }
277
+ });
278
+ JPanel jp = new JPanel(this);
279
+ for (Compo c : comps) {
280
+ jp.add(c.compo);
281
+ }
282
+
283
+ return jp;
284
+ }
285
+ }
286
+
287
+
288
+ ```
289
+
290
+ Utils.java で保存
291
+ ```java
292
+ package jp.kanagawa.caron.swing.tools;
293
+
294
+ public final class Utils {
295
+
296
+ public static void assertNull(Object o) {
297
+ if (o != null) return;
298
+ throw new RuntimeException("null はいかん。");
299
+ }
300
+
301
+ public static void assertRange(int a, int rs, int re) {
302
+ if (a >= rs && a < re) return;
303
+ throw new RuntimeException("範囲が狂っとる");
304
+
305
+ }
306
+
307
+ }
308
+
309
+ ```
310
+
311
+ 全部対応するファイル名で保存、パッケージパスを自分とこに合わせて、Dentaku.java を実行してみてください。
312
+ 画面サイズを変更しても元に戻すとちゃんとレイアウトが戻ります。
313
+