前回の質問の続きですよね?
Java - 親クラスの変数を子クラスで変更し、親クラスに返す|teratail
前回の質問をどう解決されたかわからないので複数クラスに分けましたが、内部クラス等でいいならもっと簡単な話になります。
カウンタ変数iが一定数カウントされたら、自動的にsetEnabledをtrueに変更し、ボタンが有効になるようにしたい
これはかなり本質を突いた問いでして、そういうことができれば便利なのですが、ただのint
変数にはそういう機能はありません。
Sc
の外でi
を変えてもSc
は知りようがないし、逆にSc
がi
を変えてもほかのクラスからはわかりません。
もちろんi
が変わった後にi
を見れば増えてはいます(いつ増えたのかはわからない)
簡単な解決策は直接i
を変えずに、i
を変えるメソッドを用意することです。
そうすればSc
はいつi
が変わるのかを把握できます。
こういうメソッドをセッター(setter)といいます。
Java
1import java.awt.BorderLayout;
2import java.awt.CardLayout;
3import java.awt.event.ActionEvent;
4import java.awt.event.ActionListener;
5import javax.swing.JButton;
6import javax.swing.JFrame;
7import javax.swing.JPanel;
8
9
10public class Sc extends JFrame implements ActionListener {
11 public static void main(String[] args) {
12 new Sc().setVisible(true);
13 }
14
15 private final JPanel cardPanel;
16 private final CardLayout CardLayout;
17 private final JButton toResult;
18
19 private int i = 0;
20
21 public Sc() {
22 setSize(400, 300);
23 setLocationRelativeTo(null);
24 setDefaultCloseOperation(EXIT_ON_CLOSE);
25
26 cardPanel = new JPanel();
27 CardLayout = new CardLayout();
28 cardPanel.setLayout(CardLayout);
29
30 cardPanel.add(new QuestionPanel(this), "question");
31
32 JPanel result = new JPanel();
33 result.add(new JButton("result"));
34 cardPanel.add(result, "result");
35
36 JPanel btnPanel = new JPanel();
37 toResult = new JButton("結果に進む");
38 toResult.addActionListener(this);
39 toResult.setActionCommand("result");
40 toResult.setEnabled(false);
41 btnPanel.add(toResult);
42
43 add(cardPanel, BorderLayout.CENTER);
44 add(btnPanel, BorderLayout.PAGE_END);
45 }
46
47 // public int getI() {return i;} // ゲッター(getter)
48 // public void setI(int i) {this.i = i;} // セッター(setter)
49 // ゲッターセッターでもいいのだが、「1ずつ増やす」しかしないのでより明確に
50 public void incrementI() {
51 i++;
52 if (11 <= i) {
53 toResult.setEnabled(true);
54 }
55 }
56
57 @Override public void actionPerformed(ActionEvent e) {
58 CardLayout.show(cardPanel, e.getActionCommand());
59 }
60}
61
62class QuestionPanel extends JPanel implements ActionListener {
63 private final Sc sc;
64
65 QuestionPanel(Sc sc) {
66 this.sc = sc;
67
68 JButton yes = new JButton("〇");
69 yes.addActionListener(this);
70 yes.setActionCommand("yes");
71 add(yes);
72
73 JButton no = new JButton("×");
74 no.addActionListener(this);
75 no.setActionCommand("no");
76 add(no);
77 }
78
79 @Override public void actionPerformed(ActionEvent e) {
80 sc.incrementI();
81 }
82}
ただのint
変数にはそういう機能はありません。
と言いましたが、実はそういうことができる仕組みは用意されています(Swingで活用している例はほとんど見ないのですが^^;
PropertyChangeListener (Java Platform SE 8 )
PropertyChangeSupport (Java Platform SE 8 )
Java
1import java.awt.BorderLayout;
2import java.awt.CardLayout;
3import java.awt.event.ActionEvent;
4import java.awt.event.ActionListener;
5import java.beans.PropertyChangeEvent;
6import java.beans.PropertyChangeListener;
7import javax.swing.JButton;
8import javax.swing.JFrame;
9import javax.swing.JPanel;
10import javax.swing.event.SwingPropertyChangeSupport;
11
12
13public class Sc extends JFrame implements ActionListener, PropertyChangeListener {
14 public static void main(String[] args) {
15 new Sc().setVisible(true);
16 }
17
18 private final JPanel cardPanel;
19 private final CardLayout CardLayout;
20 private final JButton toResult;
21 private final QuestionModel model;
22
23
24 public Sc() {
25 setSize(400, 300);
26 setLocationRelativeTo(null);
27 setDefaultCloseOperation(EXIT_ON_CLOSE);
28
29 model = new QuestionModel();
30 model.addPropertyChangeListener(this);
31
32 cardPanel = new JPanel();
33 CardLayout = new CardLayout();
34 cardPanel.setLayout(CardLayout);
35
36 cardPanel.add(new QuestionPanel(model), "question");
37
38 JPanel result = new JPanel();
39 result.add(new JButton("result"));
40 cardPanel.add(result, "result");
41
42 JPanel btnPanel = new JPanel();
43 toResult = new JButton("結果に進む");
44 toResult.addActionListener(this);
45 toResult.setActionCommand("result");
46 toResult.setEnabled(false);
47 btnPanel.add(toResult);
48
49 add(cardPanel, BorderLayout.CENTER);
50 add(btnPanel, BorderLayout.PAGE_END);
51 }
52
53 @Override public void actionPerformed(ActionEvent e) {
54 CardLayout.show(cardPanel, e.getActionCommand());
55 }
56
57 @Override public void propertyChange(PropertyChangeEvent evt) {
58 if (11 <= model.getI()) {
59 toResult.setEnabled(true);
60 }
61 }
62}
63
64class QuestionPanel extends JPanel implements ActionListener {
65 private final QuestionModel model;
66
67 QuestionPanel(QuestionModel model) {
68 this.model = model;
69
70 JButton yes = new JButton("〇");
71 yes.addActionListener(this);
72 yes.setActionCommand("yes");
73 add(yes);
74
75 JButton no = new JButton("×");
76 no.addActionListener(this);
77 no.setActionCommand("no");
78 add(no);
79 }
80
81 @Override public void actionPerformed(ActionEvent e) {
82 model.incrementI();
83 }
84}
85
86class QuestionModel {
87 private final SwingPropertyChangeSupport pcs = new SwingPropertyChangeSupport(this);
88
89 public void addPropertyChangeListener(PropertyChangeListener listener) {
90 pcs.addPropertyChangeListener(listener);
91 }
92
93// public void removePropertyChangeListener(PropertyChangeListener listener) {
94// pcs.removePropertyChangeListener(listener);
95// }
96
97 private int i;
98
99 public int getI() { return i; }
100
101// public void setI(int newValue) {
102// int oldValue = i;
103// i = newValue;
104// pcs.firePropertyChange("i", oldValue, newValue);
105// }
106
107 public void incrementI() {
108 pcs.firePropertyChange("i", i++, i);
109 }
110}
あまり変わり映えしませんが、変更を知れるクラスをいくつでも登録できます。
追記
内部クラスで変数を扱うことにしております。
Code
は内部クラスになっていませんが、書き間違いだとして^^;
内部クラスでいいなら話は簡単です。
外(Sc
)の変数がそのまま使えるので、i++
したついでにチェックするだけです。
Java
1import java.awt.BorderLayout;
2import java.awt.CardLayout;
3import java.awt.event.ActionEvent;
4import java.awt.event.ActionListener;
5import javax.swing.JButton;
6import javax.swing.JFrame;
7import javax.swing.JPanel;
8
9public class Sc extends JFrame implements ActionListener {
10 public static void main(String[] args) {
11 new Sc().setVisible(true);
12 }
13
14 private final JPanel cardPanel;
15 private final CardLayout cardLayout;
16 private final JButton btn_2to3;
17
18 private int i = 0;
19
20 public Sc() {
21 setSize(400, 300);
22 setLocationRelativeTo(null);
23 setDefaultCloseOperation(EXIT_ON_CLOSE);
24
25 JPanel p2 = new JPanel();
26 JButton btn02 = new JButton("C");
27 btn02.addActionListener(new Code());
28 p2.add(btn02);
29
30 JPanel p3 = new JPanel();
31 JButton btn03 = new JButton("panel03");
32 p3.add(btn03);
33
34 cardPanel = new JPanel();
35 cardLayout = new CardLayout();
36 cardPanel.setLayout(cardLayout);
37
38 cardPanel.add(p2, "panel02");
39 cardPanel.add(p3, "panel03");
40
41 btn_2to3 = new JButton("結果に進む");
42 btn_2to3.addActionListener(this);
43 btn_2to3.setActionCommand("panel03");
44
45 JPanel btnPanel = new JPanel();
46 btnPanel.add(btn_2to3);
47 btn_2to3.setEnabled(false);
48
49 add(cardPanel, BorderLayout.CENTER);
50 add(btnPanel, BorderLayout.PAGE_END);
51 }
52
53 public void actionPerformed(ActionEvent e) {
54 String cmd = e.getActionCommand();
55 cardLayout.show(cardPanel, cmd);
56 }
57
58
59 class Code implements ActionListener {
60 public void actionPerformed(ActionEvent e) {
61 i++;
62 if (i == 11) {
63 btn_2to3.setEnabled(true);
64 }
65 }
66 }
67}