回答編集履歴

2

見直しキャンペーン中

2023/07/30 04:35

投稿

TN8001
TN8001

スコア9837

test CHANGED
@@ -9,7 +9,6 @@
9
9
  * `JButton`には通常`ActionListener`を使用します(`MouseListener`は使いません)
10
10
  * こういった(詳細入力のような)ウィンドウは通常モーダルで出します(`JDialog`)
11
11
  現状詳細入力ウィンドウはモードレスなので、何個も出せてしまいます。
12
-
13
12
 
14
13
  ---
15
14
 

1

追記

2022/02/04 21:36

投稿

TN8001
TN8001

スコア9837

test CHANGED
@@ -9,3 +9,237 @@
9
9
  * `JButton`には通常`ActionListener`を使用します(`MouseListener`は使いません)
10
10
  * こういった(詳細入力のような)ウィンドウは通常モーダルで出します(`JDialog`)
11
11
  現状詳細入力ウィンドウはモードレスなので、何個も出せてしまいます。
12
+
13
+
14
+ ---
15
+
16
+ 追記
17
+
18
+ > 例えば油の種類は普通決められているのでラジオボタンなどで選択式にして変更できるようにと考えています。
19
+
20
+ `JTable`でコンボボックスも使えます(が、マストのことですので今回はスルーで結構です^^;
21
+ [How to Use Tables (The Java™ Tutorials > Creating a GUI With Swing > Using Swing Components)](https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#combobox)
22
+
23
+ > 駅のホーム天井からぶら下がってるのりば案内とかのディスプレイが機械1のタブ、情報タブは時刻表のように情報の格納場所というイメージです
24
+
25
+ わかるような、わからないような?^^;
26
+ 情報は一覧用途で、主に個別タブを見るって感じなんですかね?
27
+
28
+ タブ(=`TableModel`の行)は動的に増減するんでしょうか?(つまり「機械追加」ボタンのようなものがあるのかどうか)
29
+
30
+ > そのため表の値を変更したときにイベントを発生させてラベルの値を変えてあげる必要があります
31
+
32
+ まあいろいろなアプローチがあるとは思いますが、`TableModelListener`を使えば値の変更は検知できます。
33
+ [How to Use Tables (The Java™ Tutorials > Creating a GUI With Swing > Using Swing Components)](https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#modelchange)
34
+
35
+ 結局すべてのデータは`TableModel`が持っているわけですから、それを渡せばいいんじゃないですかね?
36
+
37
+ パネル(ウィンドウ)間であれこれちょっかいを出そうとすると、コードがすぐスパゲッティ化します。
38
+ 相互に依存したりせず、できるだけシンプルなつくりにするように心がけましょう。
39
+
40
+
41
+ ```Java
42
+ import javax.swing.JButton;
43
+ import javax.swing.JComboBox;
44
+ import javax.swing.JDialog;
45
+ import javax.swing.JFrame;
46
+ import javax.swing.JLabel;
47
+ import javax.swing.JPanel;
48
+ import javax.swing.JScrollPane;
49
+ import javax.swing.JSpinner;
50
+ import javax.swing.JTabbedPane;
51
+ import javax.swing.JTable;
52
+ import javax.swing.SpinnerNumberModel;
53
+ import javax.swing.SwingUtilities;
54
+ import javax.swing.event.TableModelEvent;
55
+ import javax.swing.event.TableModelListener;
56
+ import javax.swing.table.DefaultTableModel;
57
+ import javax.swing.table.TableModel;
58
+ import java.awt.BorderLayout;
59
+ import java.awt.GridLayout;
60
+ import java.awt.event.ActionEvent;
61
+ import java.awt.event.ActionListener;
62
+ import java.awt.event.MouseEvent;
63
+ import java.awt.event.MouseListener;
64
+
65
+
66
+ public class MyFrame extends JFrame {
67
+ public static void main(String[] args) {
68
+ new MyFrame().setVisible(true);
69
+ }
70
+
71
+ private final DefaultTableModel tableModel;
72
+
73
+ MyFrame() {
74
+ setSize(800, 600);
75
+ setLocationRelativeTo(null);
76
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
77
+
78
+ var tabbedPane = new JTabbedPane();
79
+
80
+ // csvファイルかなんかで読み込むテイで
81
+ var csv = ",ワット数,油の種類,油残量\n" +
82
+ "機械1,100,ABC,50\n" +
83
+ "機械2,200,FRE,10";
84
+ var lines = csv.split("\n");
85
+ tableModel = new DefaultTableModel(lines[0].split(","), 0);
86
+
87
+ for (var i = 1; i < lines.length; i++) {
88
+ var row = lines[i].split(",");
89
+ tableModel.addRow(row);
90
+
91
+ var machine = new MachinePanel(tableModel, i - 1);
92
+ tabbedPane.addTab(row[0], machine);
93
+ }
94
+
95
+ tabbedPane.addTab("情報", new InfoPanel(tableModel));
96
+ add(tabbedPane);
97
+ }
98
+ }
99
+
100
+ class MachinePanel extends JPanel implements TableModelListener {
101
+ private final TableModel tableModel;
102
+ private final int row;
103
+
104
+ private final JLabel watLabel;
105
+ private final JLabel oilTypeLabel;
106
+ private final JLabel oilLevelLabel;
107
+
108
+ MachinePanel(TableModel tableModel, int row) {
109
+ setLayout(new BorderLayout());
110
+ this.tableModel = tableModel;
111
+ tableModel.addTableModelListener(this);
112
+ this.row = row;
113
+
114
+ var panel = new JPanel(new GridLayout(3, 2));
115
+ panel.add(new JLabel("ワット数", JLabel.CENTER));
116
+ watLabel = new JLabel();
117
+ panel.add(watLabel);
118
+
119
+ panel.add(new JLabel("油の種類", JLabel.CENTER));
120
+ oilTypeLabel = new JLabel();
121
+ panel.add(oilTypeLabel);
122
+
123
+ panel.add(new JLabel("油残量", JLabel.CENTER));
124
+ oilLevelLabel = new JLabel();
125
+ panel.add(oilLevelLabel);
126
+ add(panel, BorderLayout.NORTH);
127
+
128
+ tableChanged(null); // 雑いw
129
+ }
130
+
131
+ @Override public void tableChanged(TableModelEvent e) {
132
+ // 本来はいろいろ情報が来るが、面倒なのでノーチェック&全更新^^;
133
+ var wat = (String) tableModel.getValueAt(row, 1);
134
+ var oilType = (String) tableModel.getValueAt(row, 2);
135
+ var oilLevel = (String) tableModel.getValueAt(row, 3);
136
+
137
+ watLabel.setText(wat);
138
+ oilTypeLabel.setText(oilType);
139
+ oilLevelLabel.setText(oilLevel);
140
+ }
141
+ }
142
+
143
+ class InfoPanel extends JPanel implements MouseListener {
144
+ private final DefaultTableModel tableModel;
145
+
146
+ private final JTable table;
147
+
148
+ public InfoPanel(DefaultTableModel tableModel) {
149
+ setLayout(new BorderLayout());
150
+ this.tableModel = tableModel;
151
+
152
+ table = new JTable(tableModel);
153
+ table.addMouseListener(this);
154
+ add(new JScrollPane(table));
155
+ }
156
+
157
+ @Override public void mouseClicked(MouseEvent e) {
158
+ var frame = (JFrame) SwingUtilities.getWindowAncestor(this);
159
+ var row = table.getSelectedRow();
160
+
161
+ // モーダルなので閉じるまで帰ってこない
162
+ new DetailEditDialog(frame, tableModel, row).setVisible(true);
163
+
164
+ printTable();
165
+ }
166
+
167
+ @Override public void mouseEntered(MouseEvent e) {}
168
+
169
+ @Override public void mouseExited(MouseEvent e) {}
170
+
171
+ @Override public void mousePressed(MouseEvent e) {}
172
+
173
+ @Override public void mouseReleased(MouseEvent e) {}
174
+
175
+ private void printTable() {
176
+ for (var row = 0; row < tableModel.getRowCount(); row++) {
177
+ for (var col = 0; col < tableModel.getColumnCount(); col++) {
178
+ var s = (String) (tableModel.getValueAt(row, col));
179
+ System.out.print(s + "\t");
180
+ }
181
+ System.out.println();
182
+ }
183
+ System.out.println();
184
+ }
185
+ }
186
+
187
+ class DetailEditDialog extends JDialog implements ActionListener {
188
+ private final DefaultTableModel tableModel;
189
+ private final int row;
190
+
191
+ private final JButton okButton = new JButton("OK");
192
+ private final JSpinner watSpinner;
193
+ private final JComboBox<String> oilTypeComboBox;
194
+ private final JSpinner oilLevelSpinner;
195
+
196
+ DetailEditDialog(JFrame owner, DefaultTableModel tableModel, int row) {
197
+ super(owner, "詳細入力 - " + tableModel.getValueAt(row, 0), true);
198
+ setSize(300, 200);
199
+ setLocationRelativeTo(owner);
200
+
201
+ this.tableModel = tableModel;
202
+ this.row = row;
203
+ var wat = Integer.parseInt((String) tableModel.getValueAt(row, 1));
204
+ var oilType = (String) tableModel.getValueAt(row, 2);
205
+ var oilLevel = Integer.parseInt((String) tableModel.getValueAt(row, 3));
206
+
207
+ var panel = new JPanel(new GridLayout(3, 2));
208
+ panel.add(new JLabel("ワット数", JLabel.CENTER));
209
+ watSpinner = new JSpinner(new SpinnerNumberModel(wat, 0, 1000, 1));
210
+ panel.add(watSpinner);
211
+
212
+ panel.add(new JLabel("油の種類", JLabel.CENTER));
213
+ oilTypeComboBox = new JComboBox<>(new String[]{"ABC", "FRE", "XYZ"});
214
+ oilTypeComboBox.setSelectedItem(oilType);
215
+ panel.add(oilTypeComboBox);
216
+
217
+ panel.add(new JLabel("油残量", JLabel.CENTER));
218
+ oilLevelSpinner = new JSpinner(new SpinnerNumberModel(oilLevel, 0, 100, 1));
219
+ panel.add(oilLevelSpinner);
220
+ add(panel, BorderLayout.NORTH);
221
+
222
+ var panel2 = new JPanel();
223
+ okButton.addActionListener(this);
224
+ var cancel = new JButton("キャンセル");
225
+ cancel.addActionListener(this);
226
+ panel2.add(okButton);
227
+ panel2.add(cancel);
228
+ add(panel2, BorderLayout.SOUTH);
229
+ }
230
+
231
+ @Override public void actionPerformed(ActionEvent e) {
232
+ if (e.getSource() == okButton) {
233
+ // 面倒なので文字列に戻したが、jimbeさんの回答のように専用のTableModelを作ったほうがいいんでしょうね
234
+ tableModel.setValueAt(String.valueOf(watSpinner.getValue()), row, 1);
235
+ tableModel.setValueAt(oilTypeComboBox.getSelectedItem(), row, 2);
236
+ tableModel.setValueAt(String.valueOf(oilLevelSpinner.getValue()), row, 3);
237
+ }
238
+ dispose();
239
+ }
240
+ }
241
+ ```
242
+
243
+ * エラーチェック全くなし
244
+ * 動的な追加削除は無考慮
245
+ 追加はいいとしても、削除は`removeTableModelListener`や`row`の振り直し等必要になりますね。