SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

作って覚えるJavaプログラミングのススメ

Java入門 (5) - Swingにおけるイベント処理

作って覚えるJavaプログラミングのススメ 第5回

内部クラスを使った方法

 もう1つの、比較的よく用いられる方法は「内部クラス」と呼ばれるものを利用する方法です。内部クラスとは、文字通り「クラスの中に作成されたクラス」のことです。実は、クラスというのはどんな場所にも定義できるのです。

package codezine.java;

import java.awt.event.*;
import javax.swing.*;

public class Sample extends JFrame {
    JLabel label;
    JTextField field;
    JButton button;
    
    public Sample(){
        this.setSize(300,200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(null);
        
        // JLabelの組み込み
        String msg0 = "<html><h3>Sample</h3></html>";
        label = new JLabel(msg0);
        label.setSize(200,30);
        label.setLocation(20,20);
        this.add(label);
        // JTextFieldの組み込み
        field = new JTextField();
        field.setSize(200,20);
        field.setLocation(20,50);
        this.add(field);
        // JButtonの組み込み
        button = new JButton("JButton");
        button.setSize(100,25);
        button.setLocation(20,80);
        button.addActionListener(new ActionAdapter());
        this.add(button);
    }

    public static void main(String[] args) {
        Sample sample = new Sample();
        sample.setVisible(true);
    }
    
    class ActionAdapter implements ActionListener {
        
        public void actionPerformed(ActionEvent ev){
            String s = field.getText();
            label.setText("あなたは、" + s + "と書きました。");
        }
    }
}

 このリストを見てください。ActionAdapterクラスの定義が、Sampleクラスの中に書かれています。フィールドやメソッドと同じように、Sampleクラスの要素の1つとしてActionAdapterクラスが書かれています。こうすれば、ActionAdapterクラスはSampleクラスの要素の1つですから、同じSampleクラス内のlabelやfieldといったフィールドもそのまま利用できます。

 また、ActionAdapterを利用するのがコンストラクタの中だけであれば、こんな書き方をすることもできます。

package codezine.java;

import java.awt.event.*;
import javax.swing.*;

public class Sample extends JFrame {
    JLabel label;
    JTextField field;
    JButton button;
    
    public Sample(){
        this.setSize(300,200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(null);
        
        // JLabelの組み込み
        String msg0 = "<html><h3>Sample</h3></html>";
        label = new JLabel(msg0);
        label.setSize(200,30);
        label.setLocation(20,20);
        this.add(label);
        // JTextFieldの組み込み
        field = new JTextField();
        field.setSize(200,20);
        field.setLocation(20,50);
        this.add(field);
        // JButtonの組み込み
        button = new JButton("JButton");
        button.setSize(100,25);
        button.setLocation(20,80);

        class ActionAdapter implements ActionListener {
            
            public void actionPerformed(ActionEvent ev){
                String s = field.getText();
                label.setText("あなたは、" + s + "と書きました。");
            }
        }

        button.addActionListener(new ActionAdapter());
        this.add(button);
    }

    public static void main(String[] args) {
        Sample sample = new Sample();
        sample.setVisible(true);
    }
    
}

 今度は、Sampleクラスのコンストラクタの中にActionAdapterクラスの定義が書かれています。こうすると、メソッドの中で宣言された変数などと同様に、そのメソッドの中(ここではコンストラクタ)だけでクラスが利用できるようになります。

 内部クラスを使った方法は比較的分かりやすくイベントリスナーを用意できますし、一応、それぞれのイベントリスナーごとにまとめられますので、すべて1クラスに詰め込むよりは分かりやすく設計できるでしょう。

無名クラスを使った方法

 これを更に突き進めると、addActionListenerの引数の()内にクラスの定義をいれてしまう、ということもできることが分かります。

package codezine.java;

import java.awt.event.*;
import javax.swing.*;

public class Sample extends JFrame {
    JLabel label;
    JTextField field;
    JButton button;
    
    public Sample(){
        this.setSize(300,200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(null);
        
        // JLabelの組み込み
        String msg0 = "<html><h3>Sample</h3></html>";
        label = new JLabel(msg0);
        label.setSize(200,30);
        label.setLocation(20,20);
        this.add(label);
        // JTextFieldの組み込み
        field = new JTextField();
        field.setSize(200,20);
        field.setLocation(20,50);
        this.add(field);
        // JButtonの組み込み
        button = new JButton("JButton");
        button.setSize(100,25);
        button.setLocation(20,80);

        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ev){
                String s = field.getText();
                label.setText("あなたは、" + s + "と書きました。");
            }
        });
        this.add(button);
    }
    
    public static void main(String[] args) {
        Sample sample = new Sample();
        sample.setVisible(true);
    }
    
}

 addActionListenerの引数に、new ActionListener(){……}という形で、ActionListener()の後にクラスの定義が書かれています。こうすることで、ActionListenerのインスタンスを作成する際にこれらの定義を組み込んだクラスが生成され、インスタンスを作成できるようになります。これが「無名クラス」と呼ばれるものです。

 無名クラスは、処理の途中にいきなりクラス定義がはめ込まれるので、正直、かなり分かりにくいです。慣れるまでは、何がどうなってるのかよくわからないかも知れませんね。

 また、その場でクラスとインスタンスが生成されるので、例えば「1つのインスタンスを複数のコンポーネントに組み込む」というようなことはできません。あまり複雑な処理を書くと無名クラスを組み込んでいるメソッドがやたらと長くなってしまうなど、弊害もあります。短い定型文程度の処理をイベントに組み込むような場合に限定的に使うもの、と考えた方がよいかもしれません。

まとめ

 今回はアクションリスナーを例に、イベントリスナーの作成方法と、さまざまな組み込み方法について説明をしました。アクションリスナーの作成そのものはそれほど難しいものではありません。「implements」というものの書き方さえ分かれば、クラス自体は簡単に作れるはずです。問題は、それをメインクラスからどう利用するのがいいかというところでしょう。

 また、アクションリスナーのさまざまな組み込み方も紹介しました。これらはすべてアクションリスナー以外のイベントリスナーでもそのまま利用できるものです。イベントリスナー組み込みの基本として、ここにあげた方法ぐらいは知識として身につけておきたいものです。

 とはいえ、いきなり全部を覚えるのは難しいでしょう。特に無名クラスなどは、実際に自分で応用してみろといわれると考え込んでしまうかもしれません。まずは、Sample自身にimplementsして実装する方法から覚えていきましょう。これは、一番よく用いられる手法で、たいていの場合はこれで何とかなるものです。

 ここにあげたものは、すべてわからないとイベント処理ができないというわけではありません。どれか1つを確実に使えるようになれば、それで済んでしまうことでしょう。まずは確実にアクションイベントの処理を書けるようになるのが先決。内部クラスや無名クラスによる方法は、その後でゆっくり学ぶ、と考えるとよいでしょう。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
作って覚えるJavaプログラミングのススメ連載記事一覧

もっと読む

この記事の著者

掌田 津耶乃(ショウダ ツヤノ)

三文ライター&三流プログラマ。主にビギナーに向けたプログラミング関連の執筆を中心に活動している。※現在、入門ドキュメントサイト「libro」、カード型学習サイト「CARD.tuyano.com」を公開...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/2194 2008/02/21 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー