JLabelの配列を作成しようとしています。クリックすると、すべてが非表示になります。問題は、ラベルの宣言に使用されるループの反復変数にアクセスする必要がある内部クラスを介してマウスリスナーを設定しようとするときに発生します。コードは自明です:
for(int i=1; i<label.length; i++) {
label[i] = new JLabel("label " + i);
label[i].addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
label[i].setVisible(false); // compilation error here
}
});
cpane.add(label[i]);
}
内部メソッド内でlabel[i]
を呼び出す代わりにthis
または多分super
を使用することでこれを克服できると思いましたが、それを理解することができませんでした。
コンパイルエラーは次のとおりです。ローカル変数iは内部クラス内からアクセスされます。最終的に宣言する必要があります `
その答えは私が考えたことのない本当にばかげたものであるに違いないと確信しています。
どんな助けもいただければ幸いです
内部(および匿名)クラスからアクセスするには、ローカル変数がfinal
である必要があります。
次のようなコードを変更できます。
for (int i = 1; i < label.length; i++) {
final JLabel currentLabel =new JLabel("label " + i);
currentLabel.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
currentLabel.setVisible(false); // No more compilation error here
}
});
label[i] = currentLabel;
}
JLSから:
使用されているが内部クラスで宣言されていないローカル変数、仮パラメーター、または例外パラメーターは、
final
として宣言する必要があります。内部クラスで使用されているが宣言されていないローカル変数は、必ず内部クラスの本体の前に (§16) を割り当てる必要があります。
リソース:
i
へのアクセスに問題がある場合は、内部クラスのスコープ外に別の変数を作成します(例:label[i].addMouseListener(...)
の前):
for(int i=1; i<label.length; i++) {
label[i] = new JLabel("label " + i);
final int localI = i;
label[i].addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
label[localI].setVisible(false);
}
});
cpane.add(label[i]);
}
プログラムでgetSource
を使用することもできます。この後、typecasting
を使用してコンポーネントにアクセスできます。それは余分なコード行を減らします、あなたのコードはこのようになります
for (int i = 1; i < label.length; i++) {
currentLabel.addMouseListener(new MouseAdapter(e) {
public void mouseClicked(MouseEvent me) {
JLabel label = (JLabel) me.getSource();
}
});
}
これは、label
がfinal
として指定されていないために発生します。
ラベルの配列を次のように宣言します。
final JLabel[] label;
の代わりに:
JLabel[] label;
MouseAdapter
は内部クラスではありません。 anonymousクラスです。匿名クラスは、それらを囲むコードのfinal
変数のみを参照できます。
匿名の内部クラスは、final
である囲んでいるメソッドの変数にのみアクセスできます。