next up previous contents
Next: 新しいイベント・クラス Up: JDK1.1のイベント・モデル Previous: これまでのモデル

Listener の導入

JDK1.1での新しいイベント処理の特徴は、イベント処理を、イベントの送り手、発生源 (Event Source)と、処理を担うイベントの受け取り手(Event Listener)の二つの 部分にはっきりと分離し、かつ、それらのペアとして把握しようとすることです。

これまでのモデルでも、イベントがどこのcomponentで発生するかは明確でした。 発生したイベントは、ある意味では「自然に」、componentの階層構造を、 上位のcontainerに向かって流れていきました。下位のcomponentで発生した イベントは、どこで受け取られてもよかった訳です。これまでのモデルでは、 送り手の側は、自分が発生したイベントを誰が受け取るかに関心を持つ必要は ありませんでした。しかし、新しいイベント・モデルでは、イベントを 発生する側が、前もって、そのイベントの受け手を決めておかなくてはなりません。

そこで登場するのが Event Listener です。Listenerは、イベントの受け手にとっても 送り手にとっても決定的に重要な意味を持ちます。これまでのモデルでは、どの componentもイベントの受け手になれたのですが、新しいイベント・モデルでは、 Listener interfaceを実装しなければ、イベントの受け手にはなれません。また、 あるオブジェクトがイベントの送り手になるということは、このListener interfaceを 実装したオブジェクトを イベントの受け手として、自分自身に登録することに他なり ません。全てのListener interfaceは、java.util.EventListenerを継承してつくられ ます。

イベントの「受け手」--- Listener

Listenerは、イベントの発生を聞き耳を立てて見守る、イベントの「受け手」であり、 そのイベントを処理する、いくつかのメソッド達から構成されるinterfaceです。 Listenerが、classではないことに注意してください。全てのListenerは、何故か、 java.utilの下にある EventListener interfaceの拡大であり、新設されたパッケージ java.awt.eventの中にいくつかのListenerが用意されています。次は、その一覧です。

----------------------------------------------------------------------------
     Listener Interface        Adapter class           Listener登録メソッド
----------------------------------------------------------------------------
     ActionListener                                   addActionListener    
     AdjustmentListener                               addAdjustmentListener  
     ComponentListener         ComponentAdapter       addComponentListener   
     ContainerListener         ContainerAdapter       addContainerListener  
     FocusListener             FocusAdapter           addFocusListener         
     ItemListener                                     addItemListener     
     KeyListener               KeyAdapter             addKeyListener   
     MouseListener             MouseAdapter           addMouseListener     
     MouseMotionListener       MouseMotionAdapter     addMouseMotionListener   
     TextListener                                     addTextListener     
     WindowListener            WindowAdapter          addWindowListener    
----------------------------------------------------------------------------

この中で出てくるAdapterとは、対応するListener interfaceを実装したクラスです。 たいていの場合、イベント処理は、Listener interfaceのメソッドを使って、 このAdapter内で行われることになるはずです。例えば、Actionイベントの処理に 用いられるActionListener interfaceでは、イベント処理は、 常に、actionPerformed()というメソッドの呼び出しによって行われます。 JDK1.1で推奨されるイベントモデルでは、全てのイベント処理は、Listener interface内のメソッド(あるいはその再定義)によって行われることになります。

naming ruleとして、「Listenerはinterface、Adapterはclass」というのを、一応の 目安として、頭に入れておけばいいでしょう。(もっとも、サンプル3では、 ButtonAdapterとでも名づけるべきクラスをButtonListenerと呼んでいます。)

イベントの「送り手」 --- Listenerの登録

Listenerがイベントの「受け手」なら、イベントの「送り手」は、 どのように準備されるのでしょうか? ここでもListenerが活躍します。 JDK1.1の新しいイベントモデルで、あるオブジェクトがイベントの「送り手」 となるのは、そのオブジェクトに対して、特定のListenerが対応づけられた時に 限られます。このモデルでは、あるボタンがいくら押されても、そのボタンに Listnerが登録されていなければ、そのボタンは、イベントをまったく発生しない ものとみなされるのです。

サンプル3のリストを見てください。次の部分が、ComponentにListenerを登録する ことによって、そのcomponentをイベントの「送り手」としているところです。 このListener登録メソッドの一覧を、前にあげておきましたが、メソッドの名前が、 規則的に名付けられているのがわかりますね。JDK1.1では、クラスやメソッドの 名前の見直しが徹底して行われています。例えば、show()をsetVisible(true)に、 hide()をsetVisible(false)に変えるという変更は、処理内容の変更を伴わない、 名前だけのものです。こうした態度は、我々も見習うべきものだと思います。

    button.addActionListener(new ButtonListener(this));
    checkbox.addItemListener(new CheckboxListener(this));
    list.addItemListener(new ListListener(this));
    choice.addItemListener(new ChoiceListener(this));
    textfield.addFocusListener(new TextFieldListener(this));
    addWindowListener(new FrameAdapter(this));

Listener登録メソッドは、引数にListenerを取ります。Javaでは、interfaceが メソッドの引数になるとか、あるオブジェクトの型の宣言部分に 使われるということがあります。 これは、それらのオブジェクトが、 このinterfaceをimplementsしているべきであることを主張しています。 逆にいうと、そのinterfaceが実装されてさえいれば、どのようなクラスに 属するオブジェクトでも構わないということになります。

== サンプル3 ===============================================================
import java.awt.*;
import java.awt.event.*;

class ButtonListener implements  ActionListener {
  Sample3 s3;
 
  public ButtonListener(Sample3 s3 ){
    this.s3 = s3 ;
  }
  public void actionPerformed(ActionEvent evt){
    s3.textfield.setText("ボタンが押されました。" );
  }
}

class CheckboxListener implements  ItemListener {
 Sample3 s3;

  public CheckboxListener(Sample3  s3){
    this.s3 = s3 ;
  }
  public void itemStateChanged(ItemEvent evt){
    if ( s3.checkbox.getState() ){
       s3.textfield.setText("チェックされました。" );
    } else {
       s3.textfield.setText("チェックが外されました。" );
    }
  }
}

class ListListener implements ItemListener {
 Sample3 s3;

  public ListListener(Sample3 s3 ){
    this.s3 = s3 ;
  }
  public void itemStateChanged(ItemEvent evt){
    s3.textfield.setText(s3.list.getSelectedItem() + "が選ばれました。" );
  }
}

class ChoiceListener implements  ItemListener {
 Sample3 s3;

  public ChoiceListener(Sample3 s3){
    this.s3 = s3;
  }
  public void itemStateChanged(ItemEvent evt){
     s3.textfield.setText(s3.choice.getSelectedItem() + "が選ばれました。" );
  }
}

class TextFieldListener implements  FocusListener{
 Sample3 s3;

  public TextFieldListener(Sample3 s3 ){
    this.s3 = s3 ;
  }
  public void focusLost(FocusEvent evt){
    s3.textfield.setText("フォーカスが無くなりました。");
  }
  public void focusGained(FocusEvent evt){
    s3.textfield.setText("フォーカスがあります。");
  }
}

class FrameAdapter extends WindowAdapter {
 Sample3 s3;

  public FrameAdapter(Sample3 s3 ){
     this.s3 = s3 ;
  }
  public void windowClosing(WindowEvent evt){
     System.exit(0);
  }
}

class Sample3 extends Frame {

  Button    button ;
  Checkbox  checkbox ;
  List      list ;
  Choice    choice ;
  Panel       panel ;
  TextField textfield ;

 Sample3(){

    button = new Button("ボタン");
    checkbox = new Checkbox("チェック");
    list = new List(1);
    list.add("リスト1");
    list.add("リスト2"); 
    list.add("リスト3");
    choice = new Choice();
    choice.add("チョイス1");
    choice.add("チョイス2");
    choice.add("チョイス3");

    panel = new Panel();
    panel.add(button);
    panel.add(checkbox);
    panel.add(list);
    panel.add(choice);
    add(panel,"North");

    textfield = new TextField();
    add(textfield,"South");

    button.addActionListener(new ButtonListener(this));
    checkbox.addItemListener(new CheckboxListener(this));
    list.addItemListener(new ListListener(this));
    choice.addItemListener(new ChoiceListener(this));
    textfield.addFocusListener(new TextFieldListener(this));
    addWindowListener(new FrameAdapter(this));

    pack();
    setVisible(true);
  }

  public static void main(String argv[]){
     new Sample3();
  }
}
=============================================================================


maruyama@wakhok.ac.jp