ボタンを押すと何かをするようにプログラムを組みます。いままでのプログラムはmainから始めて書かれた順に処理が進みましたが「ボタンを押したら」となるとそうはいきません。このような場合のマウスのクリックやキーボードの入力などを「イベント」といい、このようなプログラムのつくりを「イベントドリブン」(イベント駆動型)といいます。
前回のプログラムをクリックを認識するように作りかえます。(JButtonの機能としてクリックするとへこんではいました)
/** * ボタンにイベント */ import javax.swing.*; import java.awt.*; import java.awt.event.*; public class EventTest extends JFrame implements ActionListener { JLabel label; JButton button; int count = 0; /* コンストラクタ */ public EventTest(){ setDefaultCloseOperation(EXIT_ON_CLOSE); //終了処理を追加 label = new JLabel(count + " clicks", JLabel.CENTER); //ラベルを作る button = new JButton("Click Me!"); //ボタンを作る setLayout(new BorderLayout()); //レイアウトマネージャを指定 add(label, BorderLayout.CENTER); //ラベルを真ん中に add(button, BorderLayout.SOUTH); //ボタンを下に配置 setLocationByPlatform(true); //ウインドウの位置を自動化 pack(); //ボタンに合わせてフレームの大きさを調節 setVisible(true); //実際に表示する button.addActionListener(this); } /* イベントがあったらここに来る */ public void actionPerformed(ActionEvent e) { //イベントがbuttonで起こっていたら… if (e.getSource() == button) { //countを増加 count++; //ラベルの文字を換える。 label.setText(count + " clicks"); } } /********* main **********/ public static void main(String[] args){ /* フレームを作成(事実上のプログラム実行) */ EventTest myframe = new EventTest(); } }
これでボタンを押すとクリックの回数表示が増えていきます。
インポート文が増えます。java.awt.eventパッケージを使うなどといいます。これまでと同様、これを書いておくことで短い名前で呼び出せます。
import java.awt.event.*;
JFrameを拡張するだけでなく、イベント処理のActionListener の道具を使えるようにします。
public class EventTest extends JFrame implements ActionListener {
button, label などのオブジェクトは、MyJPanelのコンストラクタだけでなく、actionPerformed のメソッドでも使うので、ここで宣言しておきます。ブロックの中で宣言した変数やオブジェクトはそのブロックないでしか使うことができません。
JLabel label;
JButton button;
int count = 0;
count はクリックの回数を入れておくための整数型の変数です。
buttonという名前のボタンに、クリックされたことを見張る監視人をつけます。クリックを感知したら this のactionPerformed を実行します。この押されたボタンの含まれている EventTestクラスのインスタンスを指します。自分自身のクラス(から作られたインスタンス)という意味です。
ここでは EventTest からつくられたインスタンスは myframe ですが、このコンストラクタから作られるオブジェクトはさまざまな名前がつけられる可能性があり、いつも myframe ではありません。ここで仮に this として置いてインスタンスを作成した時点でそのインスタンスのことをさすようにしてあるのです。
button.addActionListener(this);
クリックを感知したらこの actionPerformed というメソッドが実行されます。(正確には作成されたインスタンス内のactionPerformedです)したがって、EventTest には、actionPerformedという部分がなければなりません。(これも正確には this で指し示されたインスタンスの中になければならない)
/* イベントがあったらここに来る */ public void actionPerformed(ActionEvent e) { if (e.getSource() == button) { //イベントがbuttonで起こっていたら… count++; //countを増加 label.setText(count + " clicks"); //ラベルの文字を換える。 } }
どんなイベントが起こったかはオブジェクトで知らされます。それが、ActionEvent e です。ActionEventクラスの eという名前のインスタンス(オブジェクト)です。(正確にはわたされるオブジェクトに、e と名前をつけたのです)
そのオブジェクトにはいろいろな情報が入っていますが、その中から e.getSource() で、イベントの発生がどこで起こったか調べます。これが button であれば、カウントを増やして、ラベルに表示しています。
この例ではイベントは一つしか起こりませんが、ボタンが2つあったり、キーボードも監視するなどというときにはこれが活躍します。
label.setText(count + " clicks") のかっこ内の、" clicks" はかっこ内を文字列にする役目も持っています。数値+文字列 は数値を文字列にしてから連結するということを思い出してください。数値だけを出したいときは、(count + " clicks") の代わりに (Integer.toString(count)) を使うか、より簡単に (count + "") とします。
上記プログラムをつくりなさい。
次のプログラムでEventTest.javaを使ってこのフレームを2つ作り、それぞれが独立にカウントすることを確認しなさい。
public class UseEventTest{ public static void main(String[] args){ EventTest myframe1 = new EventTest(); EventTest myframe2 = new EventTest(); } }
次のようなラベルを増やして、WESTやNORTHに配置してみなさい。
そのラベルは、クリックすると 100, 99, 98,... と100から開始して1ずつ減らしていきます。(増えていくラベルも残して、そちらは同時に増えていくようにする)