Java入門|イベント処理のしくみと基本

ボタンを押した瞬間、画面が反応するしくみをやさしくつかもう。

イベント処理のしくみと基本の序章

GUIアプリケーションでは、画面を表示するだけでは十分ではありません。
ユーザーがボタンを押したり、マウスを動かしたり、キーを入力したりしたときに、それに合わせて画面が反応してはじめて「使えるアプリケーション」になります。

ドラゴンボールの世界でたとえるなら、修行部屋にボタンや装置が置いてあっても、それを押したときに何も起こらなければ意味がありません。
たとえば、悟空が修行開始ボタンを押したら重力装置が動き出す、ベジータが切り替えスイッチを押したら表示が変わる、といったように、何かの操作をきっかけに処理が動くことが大切です。

この「きっかけに応じて動く仕組み」が、イベント処理です。
ここでは、ボタンを押したときに表示が変わるシンプルな例を通して、イベントとは何か、ソースとリスナは何か、どのようにして処理が呼び出されるのかを、ドラゴンボールの世界観でやさしく整理していきます。

イベントとは何か

GUIでは、ユーザーの操作をきっかけとして処理が動きます。
このときの「きっかけ」がイベントです。

たとえば、次のようなものがイベントです。

操作発生するイベントの例
ボタンを押すクリックのイベント
キーを押すキーボードのイベント
マウスを動かすマウス移動のイベント
ウィンドウを閉じるウィンドウ終了のイベント

ドラゴンボールでいえば、イベントは「修行装置に変化を起こす合図」です。
修行開始ボタンを押す、気の調整レバーを動かす、終了ボタンを押す、こうした操作が合図になって、装置側が反応します。

つまりGUIでは、プログラムが一方的に進むだけではなく、ユーザーの操作を待ちながら、そのたびに必要な処理を行うという考え方になります。

イベント処理とは何か

イベントが起きたときに、それに応じて何をするかを決める仕組みがイベント処理です。

たとえば、

  • ボタンが押されたら文字を変える
  • チェックボックスが選ばれたら表示を切り替える
  • ウィンドウを閉じたら終了する

といった処理がイベント処理です。

これまで学んできたプログラムは、上から下へ順番に処理が進むことが多かったですが、GUIでは「何かが起きたら反応する」という形になります。
ここがとても大きな違いです。

ドラゴンボールの世界でいえば、これは修行マシンが「ボタンが押されたら重力を変える」「警告ランプが点いたら表示を変える」といった動きをすることにあたります。

イベント処理で登場する3つの大事な役割

イベント処理では、次の3つの役割を押さえると理解しやすいです。

役割内容
ソースイベントが発生する側
イベント実際に起きた出来事
リスナイベントを受け取って処理する側

今回のボタンの例でいえば、次のようになります。

要素今回の例
ソースボタン
イベントボタンが押されたこと
リスナActionListener を実装したクラス

ドラゴンボール風にすると、

  • ソースは修行開始ボタン
  • イベントは「押された」という合図
  • リスナはその合図を受けて動く制御係

というイメージです。

サンプルプログラム:ボタンの文字を切り替える例

ボタンを押すと、ボタン上の文字が切り替わるプログラムです。

ファイル名:Sample3.java

import java.awt.*;
import java.awt.event.*;

public class Sample3 extends Frame
{
    private Button bt;

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

    public Sample3()
    {
        super("修行スタート画面");

        // ボタンを作成する
        bt = new Button("修行をはじめる");
        
        // フレームにボタンを追加する
        add(bt);

        addWindowListener(new SampleWindowListener());

        // ボタンが押されたときの処理を登録する
        bt.addActionListener(new SampleActionListener());

        setSize(320, 200);
        setVisible(true);
    }

    class SampleWindowListener extends WindowAdapter
    {
        public void windowClosing(WindowEvent e)
        {
            System.exit(0);
        }
    }

    class SampleActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            bt.setLabel("気を高めています");
        }
    }
}

このプログラムでできること

このプログラムを実行すると、「修行スタート画面」というタイトルのウィンドウが表示され、その中に「修行をはじめる」というボタンが現れます。

そして、そのボタンをクリックすると、ボタン上の文字が「気を高めています」に変わります。

この流れを整理すると、次のようになります。

操作結果
画面を開くボタンが表示される
ボタンを押すボタンの文字が変わる
閉じるボタンを押すアプリケーションが終了する

とてもシンプルですが、GUIのイベント処理の考え方がしっかり入っています。

ボタンを作るしくみ

まず、ボタンは Button クラスで作ります。

bt = new Button("修行をはじめる");

この記述で、「修行をはじめる」という文字が表示されたボタンが作られます。

さらに、それをウィンドウに表示するために add() を使います。

add(bt);

ここまでで、画面にボタンを置く準備ができました。

ドラゴンボール風にいえば、修行部屋の壁に「修行開始」と書かれたスイッチを取りつけたようなものです。
ただし、この段階ではまだ、押しても反応はしません。
反応させるためには、次の「イベントを受け取る準備」が必要です。

ボタンに反応させるための準備

ボタンに反応させるには、addActionListener() を使って、イベント処理の担当を登録します。

bt.addActionListener(new SampleActionListener());

この1行はとても重要です。
意味としては、「このボタンが押されたら、SampleActionListener に知らせてください」という登録です。

つまり、ボタンが勝手に処理内容を知っているわけではなく、押されたときに誰に知らせるかをあらかじめ結びつけておくのです。

ドラゴンボールでたとえるなら、修行開始ボタンに「押されたら制御係へ連絡する」という設定をしているようなものです。

ActionListener とは何か

ボタンが押されたときの処理を受け持つには、ActionListener というインターフェイスを使います。

今回の例では、次のような内部クラスを用意しています。

class SampleActionListener implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        bt.setLabel("気を高めています");
    }
}

このクラスは、ActionListener を実装したイベント処理用のクラスです。
そして、その中にある actionPerformed() メソッドが、ボタンが押されたときに呼び出される処理です。

ここで大事なのは、ActionListener を使うときは actionPerformed() を定義するということです。
これが「ボタンが押されたときに何をするか」を書く場所になります。

actionPerformed() が呼ばれるタイミング

actionPerformed() は、実際にボタンが押されたときに自動的に呼び出されます。

今回の例では、この中で次の処理をしています。

bt.setLabel("気を高めています");

つまり、ボタンが押されると、ボタンに表示されている文字が新しい文字列に変更されます。

この流れを表にするとこうなります。

順番起こること
1ユーザーがボタンを押す
2ボタンがイベントを発生させる
3登録済みのリスナに通知される
4actionPerformed() が呼ばれる
5ボタンの文字が変更される

ドラゴンボール風にいえば、

  • 悟空が修行開始ボタンを押す
  • 装置が「押された」と知らせる
  • 制御係がその合図を受け取る
  • 表示板の文字を切り替える

という流れです。

setLabel() で表示文字を変更する

今回のイベント処理では、ボタンの文字を変更するために setLabel() を使っています。

bt.setLabel("気を高めています");

このメソッドは、ボタン上の表示文字を変更するためのものです。
最初は「修行をはじめる」と書かれていたボタンが、押したあとには「気を高めています」に変わります。

このように、イベント処理では画面の見た目を変えることがよくあります。
ボタンの文字を変えるのは、その中でも分かりやすい基本例です。

プログラム全体の流れを整理する

このサンプル全体を、役割ごとに整理すると理解しやすくなります。

ウィンドウを作る

public class Sample3 extends Frame

まず、Frame を継承してウィンドウを持つクラスを作っています。

ボタンを作って配置する

bt = new Button("修行をはじめる");
add(bt);

ボタンを作成し、フレームに追加しています。

ボタンのイベント処理を登録する

bt = new Button("修行をはじめる");
add(bt);

ボタンが押されたときの担当者を登録しています。

実際の処理を書く

class SampleActionListener implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        bt.setLabel("気を高めています");
    }
}

押されたときに何をするかをここで定義しています。

画面を表示する

setSize(320, 200);
setVisible(true);

最後にウィンドウを表示します。

ソースとリスナの関係

イベント処理では、ソースとリスナの関係がとても大切です。

ソースとは

ソースはイベントが発生する側です。
今回なら Button がソースです。

リスナとは

リスナは、そのイベントを受け取って処理する側です。
今回なら SampleActionListener がリスナです。

両者の関係

ソースがイベントを出し、リスナがそれを受け取って処理します。

表にすると、こう整理できます。

用語今回の役割
ソースbt というボタン
イベントボタンが押されたこと
リスナSampleActionListener
処理メソッドactionPerformed()

この関係は、GUIを学ぶうえで何度も出てきます。
ボタンだけでなく、ほかの部品でも「ソースが知らせる」「リスナが受け取る」という形が基本です。

この図が示していること

この図では、ボタンがソースとしてイベントを発生させ、そのイベントがリスナに渡され、最後に actionPerformed() が呼ばれて表示が変化する流れを表します。
つまり、GUIではボタンを押すというユーザー操作がきっかけとなって、あらかじめ登録しておいた処理が動く、というイベント処理の基本構造が分かります。
また、addActionListener() が「ソースとリスナを結びつける役割」を持っていることが分ります。

addActionListener() の意味をもう少しやさしく見る

イベント処理の中で特に大事なのが addActionListener() です。
ここをしっかりつかむと、GUIの理解がかなり進みます。

bt.addActionListener(new SampleActionListener());

この文は、「押されたことを見張る仕組みを付ける」というより、
押されたらこの担当者に連絡する設定をすると考えると分かりやすいです。

つまり、

  • ボタンだけでは処理内容は決まらない
  • リスナだけではイベントは起きない
  • addActionListener() で両者を結びつける

という関係です。

これは、修行装置のスイッチと制御係を配線でつなぐようなものです。
配線しておけば、スイッチが押された瞬間に制御係が動けます。

ActionEvent の役割

actionPerformed() の引数には ActionEvent e があります。

public void actionPerformed(ActionEvent e)

今回はこの e を直接使っていませんが、この中には「どのイベントが起きたか」という情報が入っています。
イベント処理では、こうしたイベントオブジェクトを使って詳しい情報を取り出すこともできます。

今の段階では、まず「ボタンが押されたときに actionPerformed() が呼ばれ、そのとき ActionEvent が渡される」と理解しておけば十分です。

GUIではイベント処理が中心になる

GUIアプリケーションでは、画面を作ることも大切ですが、それ以上にユーザーの操作にどう反応するかが大切です。
なぜなら、GUIは人が使うための画面だからです。

ラベルを表示するだけなら静かな画面ですが、ボタンを押して文字が変わるようになると、一気に「操作できるアプリケーションらしさ」が出てきます。

この先GUIを学んでいくと、

  • ボタンを押したらメッセージを表示する
  • 入力欄に書いた文字を読み取る
  • チェックボックスの状態で動きを変える
  • マウス操作やキー入力に反応する

といった広がりが出てきます。
そのすべての基本にあるのが、今回のイベント処理の考え方です。

はじめてイベント処理を学ぶときに戸惑いやすい点

イベント処理は、最初は少し独特に感じやすいです。
戸惑いやすい点を整理すると、次のようになります。

戸惑いやすい点理由
すぐに処理が書かれていないボタンを押したときの処理が別クラスにあるため
addActionListener() の意味が見えにくい登録という考え方に慣れていないため
actionPerformed() が勝手に呼ばれるように見えるGUI側がイベント発生時に自動で呼ぶため
ソースとリスナの関係が分かりにくい発生する側と処理する側が分かれているため

でも、次の形で覚えるとかなり分かりやすくなります。

イベント処理の基本形

  1. 部品を作る
  2. リスナを用意する
  3. addActionListener() で登録する
  4. イベントが起きる
  5. actionPerformed() が呼ばれる

この流れさえ押さえれば、最初の理解としては十分です。

この内容でつかんでおきたいこと

今回のテーマでいちばん大切なのは、GUIでは操作をきっかけに処理が動くという考え方です。
ボタンを置くだけではなく、そのボタンが押されたときにどうするかを登録しておく必要があります。

そして、そのために登場するのが次の要素です。

大切な要素意味
Buttonイベントの発生元になる部品
ActionListenerボタン操作を受け取るための仕組み
addActionListener()ボタンと処理担当を結びつける
actionPerformed()実際に処理を書く場所
ActionEvent発生したイベントの情報

この流れが見えてくると、GUIアプリケーションはただ画面を表示するだけのものではなく、人の操作に反応して変化する仕組みでできていることが分かってきます。