教育サーバーのページ
オンラインテキスト目次
ソフトウエア基礎演習
Javaでは、ウィンドウやボタン、スクロールバーなどのGUI(Graphical User Interface)を作成することは可能である。そのために、AWT(Abstract Window Toolkit)というパッケージを利用してプログラミングする。このAWTを利用して記述したプログラムは、どのコンピュータ上で実行しても同じように動作する。 AWTではフレームというウィンドウがベースとなって、そのフレームにさまざまなウィンドウやボタンなどの部品を配置する。
パッケージJava2には、たくさんのクラスがあり、それぞれの機能ごとにグループに分けて提供されている。ある機能を実現するためにグループ化されたクラスの集まりをパッケージという。
イベントドリブン(イベント駆動)一般に、ウィンドウをもったアプリケーションを作る場合には、イベントドリブン(イベント駆動)という考え方を理解する必要がある。ウィンドウシステムでは、ユーザはマウスをクリックしたり、ドラッグしたりする。また、他のアプリケーションが起動されて、ウィンドウが重なったりする。このような「何事かが起きる」こと、あるいはその「何事か」をイベントとよぶ。
イベントドリブン(イベント駆動)型アプリケーションユーザがマウスをクリックした場合、それはイベントとなる。イベントドリブン型アプリケーションでは、そのイベントに対して、自分のアプリケーションがどう対応・処理するのかを記述する。ボタンやメニューなどのあるアプリケーションをGUIアプリケーションと呼ぶが、イベントドリブン型でもある。
イベント処理の仕組みJavaでは、イベントの発生源をイベントソースと呼ぶ。ボタンやラベルなどほとんどのコンポーネントがイベントソースとなる。一方,イベントを受け取る側をイベントリスナと呼ぶ。イベントリスナは、イベントソースからイベントを受け取り、イベントに対する処理をおこなう。Javaでは、イベントソースでイベントが発生すると、自分自身に登録されているイベントリスナにそのことを知らせ、予め定義されている処理を実行する。登録するイベントリスナは、イベントソースと、そこで発生するイベントにより異なるので、それぞれの状況に応じたイベントリスナを登録する必要がある。
AWTによるGUIアプリケーション作成の流れは以下のようになる。
AWTによるGUIアプリケーション作成では、フレームというウィンドウがベースとなり、そのウィンドウの上にウィンドウやボタンなどのGUI部品を配置する。 特に、このGUI部品をコンポーネントと呼び、AWTプログラムはこのコンポーネントを組み合わせて1つのウィンドウを構成していく。 複数のコンポーネントをまとめたものをコンテナと呼び、新たなコンポーネントとしてみなしたり、コンテナの中にコンテナを包含できる。フレームは汎用的なコンテナであり、Frameクラスを使って作成できる。 コンポーネントをどのようにフレームに配置するかを指示するためには、レイアウトマネージャにレイアウト方式を指定する必要がある。実際には、AWTではレイアウトマネージャがコンポーネントのレイアウトを自動的に実行する。
次のプログラム MyWinApp.java
はフレームというウィンドウをベースとした普通のウィンドウを表示するプログラムである。 このプログラムを実行することで表示されるウィンドウは、見た目は普通のウィンドウであるので、その右上の終了ボタンで終了できそうだが、実際には終了することはできない。これを終了するためには、Ctrl+Cなどで強制終了させる必要がある。
import java.awt.*; public class MyWinApp { public static void main(String[] args) { Frame f = new Frame(); f.setSize(300, 200); f.setVisible(true); } }実行例は、たとえば次のようである。
% java MyWinApp ... .... ウィンドウシステムを強制終了させる場合には、コマンドプロンプトウィンドウ上でCtrl+Cを入力する。プログラムの説明
プログラム前半の
Frame f = new Frame();では、新しいフレーム(基本的なウィンドウ)オブジェクトを作成している。
f.setSize(300, 200);では、ウィンドウの横幅を300、高さを200に設定している。
f.setVisible(true);は、ウィンドウの表示命令を示している。
次のプログラム
プログラムの説明
プログラム前半の
Windowを閉じるイベントを処理するイベントリスナーはWindowListenerの
はずであるが、ここではWindowAdapterというクラスを使っている。これは
なぜであろうか。
比較としてWindowListenerを使って上記と同様の動作をするプログラムを書いてみる。
WindowListenerはインタフェースなので、extendsでなくimplements
を使う。インタフェースとは、メソッドしかないクラスのようなものである。
インタフェースではどういうメソッドを使うかといった宣言だけがされていて、
メソッド自体は定義されていない。
そしてインタフェースを使う時(実装するという)には、
このメソッドを全て定義する必要がある(定義しないとエラーが出る)。
このため、上記では、windowOpened(), windowClosed()... といった、
WindowListenerインタフェースで定義されている抽象メソッドを全て定義している。
これを省略することはできない。
これでは面倒なので、全てのメソッドを定義したAdapterクラスが用意されている。
Adapterクラスを使う(継承する)と、自分が定義したいメソッドだけを定義すればよくなる。MyWinApp1.javaでは、WindowAdapterを使用しているため、定義したい
windowClosing()メソッドだけを書けば良く、他のwindowOpened(),windowClosed()...
といったメソッドは書かなくても良い。もちろん、書きたい場合は書けばよい。2. 普通に終了できる機能をもつウィンドウを表示するプログラムの説明
MyWinApp1.java
はフレームというウィンドウをベースとした普通のウィンドウを表示するプログラムである。 このプログラムを実行することで表示されるウィンドウは、その右上にある終了ボタンで終了できる。
import java.awt.*;
import java.awt.event.*;
class MyFrame extends Frame {
public MyFrame() {
setSize(300, 200);
addWindowListener(new MyWindowAdapter());
}
}
class MyWindowAdapter extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
public class MyWinApp1 {
public static void main(String[] args) {
MyFrame f = new MyFrame();
f.setVisible(true);
}
}
実行例は、たとえば次のようである。 % java MyWinApp1
...
....
ウィンドウのクローズボタンをクリックすることで、ウィンドウシステムを正常に終了させる
ことができる
class MyFrame extends Frame
以下では、新しいフレームクラスMyFrameをFrameクラスを継承して定義している。
addWindowListner(new MyWindowAdapter());
では、イベントソースであるウィンドウシステムとイベントリスナであるMyWindowAdapterとを関連付けている。これによって、WindowEventを受け取るイベントリスナを指定している。つまり、イベントソースであるウィンドウのクローズボタンをクリックしたときには、ウィンドウクローズを通知するイベントがイベントリスナに伝えられる。アプリケーションはそのイベントリスナで定義されているメソッドwindowClosing(WindowEvent e)を起動し、終了処理を実行する。
class MyWindowAdapter extends WindowAdapter
では、イベントリスナーである MyWindowAdapterクラスはWindowAdapterクラスを継承して作成している。
public void windowClosing(WindowEvent e){
System.exit(0);}
では、プログラムを正常終了するための処理が記述されている。
import java.awt.*;
import java.awt.event.*;
class MyFrame extends Frame {
public MyFrame() {
setSize(300,200);
addWindowListener(new MyWindowListener());
}
}
class MyWindowListener implements WindowListener {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
public void windowOpened(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}
public class MyWinApp2 {
public static void main(String[] args) {
MyFrame f = new MyFrame();
f.setVisible(true);
}
}
次のプログラム MyWinApp1n.java
は、上記のMyWinApp1n.java
に対してさらに、タイトルを表示できるようにしたプログラムである。
import java.awt.*; import java.awt.event.*; class MyFrame extends Frame { public MyFrame() { setTitle("My Window Application"); setSize(300, 200); addWindowListener(new MyWindowAdapter()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyWinApp1n { public static void main(String[] args) { MyFrame f = new MyFrame(); f.setVisible(true); } }
実行例は、たとえば次のようである。
% java MyWinApp1n
プログラムの説明
プログラム前半の
setTitle("My Window Application");では、フレームにタイトルを表示している。
次のプログラム MyButtonTest.java
は、GUIでよく使われるコンポーネントであるボタンが配置されたウィンドウを表示できるようにしたプログラムである。
import java.awt.*; import java.awt.event.*; class MyFrame extends Frame { Button b1; public MyFrame() { setTitle("My Button Application"); setSize(300, 200); setLayout(new FlowLayout()); b1 = new Button("Button1"); add(b1); addWindowListener(new MyWindowAdapter()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyButtonTest { public static void main(String[] args) { MyFrame f = new MyFrame(); // f.show(); f.setVisible(true); } }実行例は、たとえば次のようである。
% java MyButtonTest
プログラムの説明
プログラム前半の
setLayout(new FlowLayout());では、左から右方向にボタンを配置することを示す。
b1 = new Button("Button1");では、"Button1"というラベルのボタンオブジェクトを生成することを示す。
add(b1);では、生成されたボタンオブジェクトをフレームオブジェクトに追加することを示す。
次のプログラム MyButtonTest1.java
は、GUIでよく使われるコンポーネントであるボタンが配置されたウィンドウを表示できるようにしたプログラムである。
import java.awt.*; import java.awt.event.*; class MyFrame extends Frame { Button b1, b2, b3; public MyFrame() { setTitle("My Button Application"); setSize(300, 200); setLayout(new FlowLayout()); b1 = new Button("Button1"); add(b1); b2 = new Button("Button2"); add(b2); b3 = new Button("Button3"); add(b3); addWindowListener(new MyWindowAdapter()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyButtonTest1 { public static void main(String[] args) { MyFrame f = new MyFrame(); // f.show(); f.setVisible(true); } }実行例は、たとえば次のようである。
% java MyButtonTest
プログラムの説明
プログラム前半の
setLayout(new FlowLayout());では、左から右方向にボタンを配置することを示す。
b1 = new Button("Button1"); b2 = new Button("Button2"); b3 = new Button("Button3");では、"Button1"、"Button2"、"Button3"という3つのラベルのボタンオブジェクトを生成することを示す。
add(b1); add(b2); add(b3);では、生成された3つのボタンオブジェクトをフレームオブジェクトに追加することを示す。
AWTを使ったGUIアプリケーションの作成では、イベントに対する処理を、プログラム内で以下のような手順でおこなう必要がある。
次のプログラム MyButtonTest2n.java
は、ボタンが押されたことに対してイベント処理を施したプログラムである。
import java.awt.*; import java.awt.event.*; class ButtonTestFrame extends Frame implements ActionListener { Button b1, b2, b3; public ButtonTestFrame() { setTitle("My Button Application"); setSize(300, 200); addWindowListener(new MyWindowAdapter()); setLayout(new FlowLayout()); b1 = new Button("Button1"); b2 = new Button("Button2"); b3 = new Button("Button3"); b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this); add(b1); add(b2); add(b3); } public void actionPerformed(ActionEvent ae) { if (ae.getSource() == b1) System.out.println("Button1がクリックされました"); else if (ae.getSource() == b2) System.out.println("Button2がクリックされました"); else if (ae.getSource() == b3) System.out.println("Button3がクリックされました"); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyButtonTest2n { public static void main(String[] args) { ButtonTestFrame f = new ButtonTestFrame(); // f.show(); f.setVisible(true); } }実行例は、たとえば次のようである。
% java MyButtonTest2n
プログラムの説明
このプログラムのイベント処理では、イベントソースであるButtonクラスから発生したイベント を、イベントリスナであるButtonTestFrameクラスとMyWindowAdapterクラスに伝達することで 処理がおこなわれる。
class ButtonTestFrame extends Frame implements ActionListnerでは、ボタンが押されたというイベントを受け付け、それに対する処理を実行するために、ButtonTestFrameクラスがActionListnerインタフェースを実装していることを表す。
public void actionPerformed(ActionEvt ae){ if (ae.getSource() == b1) System.out.println("Button1がクリックされました"); else if (ae.getSource() == b2) System.out.println("Button2がクリックされました"); else if (ae.getSource() == b3) System.out.println("Button3がクリックされました"); }は、ActionListnerインタフェースにおいて実装されねばならないメソッドであり、ボタンが押された際に実行される処理が記述されている。この場合には、ボタンが押された場合には、"Button がクリックされました"という文字列が標準出力に表示されことを示している。actionPerformed()メソッドの引数aeにはボタンがクリックされたイベント情報が入っている。このオブジェクトaeはボタンがクリックされてときに生成される。getSource()メソッドはイベントソースを見つけるために利用する。
b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this);では、ボタンに対してイベントリスナーを登録している。これによって、ボタンをクリックされたことにより発生するイベントを感知してactionPerformed()メソッドを呼び出すことができるようになる。
class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } }では、リスナーインターフェイスを実装しないで、WindowAdaperを継承したMyWindowAdapterを定義している。これは、複数のリスナーメソッドをもつリスナーインタフェイスでは不要なリスナーメソッドを実装しなくてならないという問題を解決するために提供されているものである。アダプタークラスは、リスナーインタフェイスがあらかじめ空のリスナーメソッドを実装しており、このクラスを継承してイベントリスナーを作成すれば、余計なリスナーメソッドを実装しなくてもよいものである。
テキストフィールドは1行のテキストが入力できる画面上の領域である。 テキストフィールドの内容はキーボードを使って編集できる。
import java.awt.*; import java.awt.event.*; class MyFrame extends Frame implements ActionListener { Button b1; TextField t; public MyFrame() { setSize(300,200); addWindowListener(new MyWindowAdapter()); setLayout(new FlowLayout()); t = new TextField("Initial Value"); add(t); b1 = new Button("Push"); add(b1); b1.addActionListener(this); } public void actionPerformed(ActionEvent ae) { // TextFieldの現在の値を標準出力に表示する System.out.println(t.getText()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e){ System.exit(0); } } public class MyTextFieldTest { public static void main(String[] args) { MyFrame f = new MyFrame(); f.setVisible(true); } }
TextFieldオブジェクトにはgetText()メソッドがあり、現在のテキストフィールド に入っている値を得ることができる。
チェックボックスは"ON"と"OFF"の2つの状態を持つ一種のボタンである。
import java.awt.*; import java.awt.event.*; class MyFrame extends Frame implements ActionListener { Button b1; Checkbox c1, c2, c3; public MyFrame() { setSize(300,200); addWindowListener(new MyWindowAdapter()); setLayout(new FlowLayout()); c1 = new Checkbox("1"); add(c1); c2 = new Checkbox("2"); add(c2); c3 = new Checkbox("3"); add(c3); b1 = new Button("Push"); add(b1); b1.addActionListener(this); } public void actionPerformed(ActionEvent ae) { // Checkboxの現在の値を標準出力に表示する System.out.println("checkbox1 is " + c1.getState()); System.out.println("checkbox2 is " + c2.getState()); System.out.println("checkbox3 is " + c3.getState()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e){ System.exit(0); } } public class MyCheckboxTest { public static void main(String[] args) { MyFrame f = new MyFrame(); f.setVisible(true); } }
CheckboxオブジェクトにはgetState()メソッドがあり、現在のチェックボックスの 状態(true=選択、false=未選択)を返す。
ラジオボタンはいくつかの選択肢の中から1つだけを選べるようなボタン の一種である。Javaでは CheckboxクラスとCheckboxGroupクラスを使ってラジオボタンを作る。
import java.awt.*; import java.awt.event.*; class MyFrame extends Frame implements ActionListener { Button b1; CheckboxGroup g; Checkbox c1, c2, c3; public MyFrame() { setSize(300,200); addWindowListener(new MyWindowAdapter()); setLayout(new FlowLayout()); g = new CheckboxGroup(); c1 = new Checkbox("1", false, g); add(c1); c2 = new Checkbox("2", false, g); add(c2); c3 = new Checkbox("3", false, g); add(c3); b1 = new Button("Push"); add(b1); b1.addActionListener(this); } public void actionPerformed(ActionEvent ae) { // Checkboxの現在の値を標準出力に表示する System.out.println("checkbox1 is " + c1.getState()); System.out.println("checkbox2 is " + c2.getState()); System.out.println("checkbox3 is " + c3.getState()); Checkbox c = g.getSelectedCheckbox(); if (c != null) { System.out.println(c.getLabel() + " is selected."); } else { System.out.println("No one is selected."); } } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyRadioButtonTest { public static void main(String[] args) { MyFrame f = new MyFrame(); f.setVisible(true); } }
先にCheckboxGroupのオブジェクトを作っておき、 c1 = new Checkbox("1", false, g)と いう風にCheckboxオブジェクトを生成する時に指定する。この例の "1"はラジオボタンの名前、falseは初期状態(未選択、trueなら選択)、 gがCheckboxGroupオブジェクトである。 現在選択されているラジオボタン(Checkboxオブジェクト)は CheckboxGroupオブジェクトのgetSelectedCheckbox()メソッドで得ることができる。 これで得たCheckboxオブジェクトの名前は getLabel()メソッドで得ることができる。
テキストエリアは複数の行からなるテキスト領域である。
import java.awt.*; import java.awt.event.*; class MyFrame extends Frame implements ActionListener { Button b1; TextArea t; public MyFrame() { setSize(200,200); addWindowListener(new MyWindowAdapter()); setLayout(new FlowLayout()); t = new TextArea("Initial Value", 6, 20); add(t); b1 = new Button("Push"); add(b1); b1.addActionListener(this); } public void actionPerformed(ActionEvent ae) { // TextAreaの現在の値を標準出力に表示する System.out.println(t.getText()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyTextAreaTest { public static void main(String[] args) { MyFrame f = new MyFrame(); f.setVisible(true); } }
上記の例では、 t = new TextArea("Initial Value", 6, 20); として、6行,20列のテキストエリアを生成している。"Initial Value" は初期のテキストエリアの内容である。
MyWinApp.java
を書いて実行してみよ。
実際にウィンドウを終了してみよ。
MyWinApp1.java
を書いて実行してみよ。
さらに、ウィンドウサイズを480 x 300に変えて実行してみよ。
MyWinApp1n.java
を書いて実行してみよ。
さらに、ウィンドウタイトルを"New Window Application"に変えて実行してみよ。
MyButtonTest.java
を書いて実行してみよ。
さらに、GUI部品であるボタンの名前を「ボタン」に変えて実行してみよ。
MyButtonTest1.java
を書いて実行してみよ。
さらに、GUI部品である4つのボタンを2X2の格子上に配置して表示してみよ。
この場合、setLayout(new FlowLayout());の代わりにsetLayout(new GridLayout(2,2));を使うこと。
MyButtonTest2n.java
を書いて実行してみよ。
さらに、標準出力に表示される文字列を英語に直して表示せよ。
MyButtonTest.java
をボタンを押すと、ボタンに書かれた文字が"Pressed"に変わるように
プログラムを修正せよ。ボタンに書かれた文字を変更するメソッドは、
API仕様などで調べよ。
MyButtonTest.java
でボタンに書かれた文字が、ボタンを押すたびに"Black","White"と交互に
変わるようにプログラムを修正せよ。現在ボタンに書かれた文字を得る
メソッドが存在する。API仕様などで調べよ。
MyTextFieldTest.java
にもう一つTextFieldを追加せよ。さらにボタンを押した場合に、
2つのTextFieldの内容が同一なら"Equal"、違うなら "Not Equal"と
標準出力に表示するようにせよ。
MyCheckboxTest.java
でそれぞれのチェックボックスの名前を"RED","GREEN","BLUE"とせよ。
さらにボタンを押した場合に、
3つのチェックボックスが全て選択された場合に、"White color"と
標準出力に表示するようにせよ。
MyTextAreaTest.java
にもう一つTextAreaを追加せよ。さらにボタンを押した場合に、
2つのTextAreaの内容を標準出力に表示するようにせよ。