ActionListener組み込みのアレンジ


なぜエラーになったのか? それは、ActionAdapterのクラスからは、Sampleクラス内のフィールドが「見えない」からです。JLabelやJTextFieldといったコンポーネントは、Sampleクラス内にフィールドとして用意されています。これらは、ActionAdapterクラスからは、そのままでは利用できないのです。なぜなら、ActionAdapterはSampleとは別のクラスなのですから。

これを利用するためには、実行中のSampleインスタンスを何らかの方法で取得し、その中のフィールドを利用する必要があります。けれど、一見すると何の関係もないActionAdapterからどうやって実行中のSampleインスタンスを取り出せばいいのか? 途方にくれてしまいますね。

この問題を解決するにはどうすればよいのか? 結局、「ActionAdapterが別のクラスである」からこういう問題が起こるのです。Sampleクラス自身にActionListenerの機能を組み込んでしまえば、このような問題も起こりません。
import java.awt.*;
import java.awt.event.*;

public class Sample extends Frame implements ActionListener {
  Label label1;
  TextField field1;
  Button button1;

  public static void main(String[] args){
    new Sample();
  }
  
  public Sample(){
    this.setLayout(null);
    this.setSize(200,140);
    label1 = new Label("こんにちは!");
    field1 = new TextField();
    button1 = new Button("Click");
    label1.setBounds(20,40,160,20);
    field1.setBounds(20,70,160,20);
    button1.setBounds(50,100,100,20);
    button1.addActionListener(this);
    this.add(label1);
    this.add(field1);
    this.add(button1);
    this.setVisible(true);
  }
  
  public void actionPerformed(ActionEvent ev){
    String s = field1.getText();
    label1.setText(s + "と書きました。");
  }
}
ボタンをクリックすると、入力したテキストを調べてテキストを表示します。

これがその例です。Sampleの部分にimplements ActionListenrがつけられていますね。そしてアクションリスナーの組み込みでは、button1.addActionListener(this);というようにthisを指定しています。thisは、インスタンス自身を示すものでしたね。こうすることで、自分自身をリスナーとして登録していたわけです。

この他に「アクションリスナーのクラスを、Sampleクラスの中にクラスごと組み込んでしまう」といった方法もあります。これは、以下のような形で記述します。
import java.awt.*;
import java.awt.event.*;

public class Sample extends Frame {
  Label label1;
  TextField field1;
  Button button1;

  public static void main(String[] args){
    new Sample();
  }
  
  public Sample(){
    this.setLayout(null);
    this.setSize(200,140);
    label1 = new Label("こんにちは!");
    field1 = new TextField();
    button1 = new Button("Click");
    label1.setBounds(20,40,160,20);
    field1.setBounds(20,70,160,20);
    button1.setBounds(50,100,100,20);
    button1.addActionListener(new ActionAdapter());
    this.add(label1);
    this.add(field1);
    this.add(button1);
    this.setVisible(true);
  }
  
  class ActionAdapter implements ActionListener {
    public void actionPerformed(ActionEvent ev){
      String s = field1.getText();
      label1.setText(s + "と書きました。");
    }
  }
}

よく見ると、ActionAdapterクラスの定義そのものがSampleクラスの中に組み込まれてしまっていることがわかるでしょう。このように「クラスの中に定義されているクラス」のことを「内部クラス(インナークラス)」と呼びます。内部クラスは、Sampleクラスの中にクラスの要素のひとつとして書かれていますから、Sampleクラス内のフィールドやメソッドを自由に利用することができます。

アクションリスナーの組み込み方はいろいろとありますが、ここであげた「自分自身にimplementsしてしまう方法」と「内部クラスとして持たせる方法」がもっとも基本となるものといってよいでしょう。この2つの方法を使えるようになれば、イベントリスナーの基本はマスターできます。ちょっとわかりにくいかも知れませんが、実際に何度かソースコードを自分で書いてみれば、自然と意味がわかってくるものですよ!


バックナンバー

はじめてのJava(1)「Javaを手に入れよう」
はじめてのJava(2)「環境変数をマスターする」
はじめてのJava(3)「Javaのプログラムを動かそう」
はじめてのJava(4)「mainメソッドを使おう」
はじめてのJava(5)「制御文を使おう」
はじめてのJava(6)「クラスとインスタンスをマスターしよう」
はじめてのJava(7)「AWTのコンポーネントを使おう」