教育サーバーのページ
オンラインテキスト目次
ソフトウエア基礎演習

GUIアプリケーション (Swing)

SwingはAWTの後継として1997年にリリースされた。基本的な部分はAWTの機能を踏襲して作成されているが、GUI部品の外見を実行時に変更できたり、多機能どの利点がある。

SwingのGUI部品には、以下のような特徴がある。

100% ピュアJavaである
Swingは全部Javaで記述されている。それゆえに、クロスプラットホームを実現していると言える。従来のAWTのGUI部品を使って書いたJavaプログラムは、動作としてはOSを超えて同じであったが、「見かけ(ルック&フィール)」はOSごとにそれぞれ異なっていた。SwingのGUI部品を使えば,動作だけでなく、見かけも含めて統一可能である。

実行時にルック&フィールを切り替え可能である
ルック&フィールを統一できるだけではなく、複数のルック&フィールを用意しておいて、実行時に切り替えることができる。この機能は「着脱可能な」(Pluggable)ルック&フィールと呼ばれる。
きめ細かい設定やカスタマイズが可能
AWTのGUI部品では、ボタンなどにはテキストしか表示できないが、Swingではテキスト以外にも、比較的簡単に画像ファイルを貼り付けたり、自分でグラフィックスを描画したりできる。また、クラスライブラリは、こうした柔軟な処理を体系的に行なえるような構成になっている。

JFrameクラスを使ってGUIアプリケーションを作成する

SwingによりGUIアプリケーションを作成する場合、ボタンやラベル、メニューなどのGUI部品を自由に組み合わせる。そのために、GUI部品を入れるための「器」を用意することが必要となり、これをコンテナとよぶ。 Swingによりアプリケーションを作成する場合には、土台となるコンテナには、JFrameクラスを利用することが一般的である。JFrameは、Swingパッケージに含まれるクラスの一つであり、アプリケーションのウィンドウを作るために利用されるクラスである。

JFrameクラスを使ったGUIアプリケーション作成の流れは以下のようになる。

  1. javax.swingパッケージのimport
  2. フレームクラスのインスタンスの作成
  3. コンテントペイン(中間コンテナ)の取得
  4. レイアウト方式の指定
  5. GUI部品(コンポーネント)のインスタンス(オブジェクト)の生成
  6. 生成されたGUI部品(コンポーネント)オブジェクトの配置
  7. 表示

1. 普通に終了できる機能をもたないウィンドウを表示するプログラムの説明

次のプログラム MyWinApp.java はフレームというウィンドウをベースとした普通のウィンドウを表示するプログラムである。 このプログラムを実行することで表示されるウィンドウは、見た目は普通のウィンドウであるので、その右上の終了ボタンで終了できそうだが、実際には終了することはできない。これを終了するためには、Ctrl+Cなどで強制終了させる必要がある。

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

public class MyWinApp{
    public static void main(String[] args){
       JFrame f = new JFrame();
       f.setSize(300, 200);
       f.setVisible(true);
    }
}
実行例は、たとえば次のようである。
% java MyWinApp
...
....
ウィンドウシステムを強制終了させる場合には、コマンドプロンプトウィンドウ上でCtrl+Cを入力する。
プログラムの説明

プログラム前半の

JFrame f = new JFrame();
では、新しいフレーム(基本的なウィンドウ(JFrame))オブジェクトを作成している。
f.setSize(300, 200);
では、ウィンドウの横幅を300、高さを200に設定している。
f.setVisible(true);
は、ウィンドウの表示命令を示している。

2. 普通に終了できる機能をもつウィンドウを表示するプログラムの説明

次のプログラム MyWinApp1.java はフレームというウィンドウをベースとした普通のウィンドウを表示するプログラムである。 このプログラムを実行することで表示されるウィンドウは、その右上にある終了ボタンで終了できる。

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

class MyFrame extends JFrame
{
    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 JFrame
では、新しいフレームクラスMyFrameをJFrameクラスを継承して定義している。
addWindowListner(new MyWindowAdapter());
では、イベントソースであるウィンドウシステムとイベントリスナであるMyWindowAdapterとを関連付けている。これによって、WindowEventを受け取るイベントリスナを指定している。つまり、イベントソースであるウィンドウのクローズボタンをクリックしたときには、ウィンドウクローズを通知するイベントがイベントリスナに伝えられる。アプリケーションはそのイベントリスナで定義されているメソッドwindowClosing(WindowEvent e)を起動し、終了処理を実行する。
class MyWindowAdapter extends WindowAdapter
では、イベントリスナーである MyWindowAdapterクラスはWindowAdapterクラスを継承して作成している。
public void windowClosing(WindowEvent e){
       System.exit(0);} 
では、プログラムを正常終了するための処理が記述されている。

3. タイトルもつウィンドウを表示するプログラムの説明

次のプログラム MyWinApp1n.java は、上記のMyWinApp1n.javaに対してさらに、タイトルを表示できるようにしたプログラムである。

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

class MyFrame extends JFrame
{
    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");
では、フレームにタイトルを表示している。

4. 1つのボタンが配置されたウィンドウを表示するプログラムの説明

GUI部品の組み込み GUIアプリケーションの構築では、アプリケーションの土台となる「入れ物」(コンテナ)の中に必要なGUI部品を組み込んでいく。 通常、コンテナとなるGUI部品には他のGUI部品を組み込むことができるが、今回利用したJFrameクラス(JDialog, Jwindow, JAppletも)では、直接、コンテナにGUI部品を組み込むことはできない。ここでは、GUI部品の追加は、コンテナから取得したcontentPaneに対しておこなう。 GUIアプリケーションを作成する際に、重要なことはGUI部品をコンテナ上にうまくレイアウト(配置)して、使いやすいユーザインターフェイスとすることが必要である。Swingを利用したGUIアプリケーションでは、GUI部品を配置する場合、レイアウトマネージャを使用する。

次のプログラム MyButtonTest.java は、GUIでよく使われるコンポーネントであるボタンが配置されたウィンドウを表示できるようにしたプログラムである。

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

class MyFrame extends JFrame
{
    Container contentPane;
    Button b1;
    public MyFrame(){
       Container contentPane = getContentPane();
       setTitle("My Button Application");
       setSize(300, 200);
       contentPane.setLayout(new FlowLayout());
       b1 = new Button("Button1");
       contentPane.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

プログラムの説明

プログラム前半の

Container contentPane = getContentPane();
では、JFrameオブジェクトからコンテントペインと呼ばれるコンテナを取得することを示す。 プログラム前半の
content.Pane.setLayout(new FlowLayout());
では、FlowLayoutレイアウトマネージャのインスタンスを生成し、作成したレイアウトのインスタンスをコンテナにセットすることで、左から右方向にボタンを配置することを 示す。
b1 = new Button("Button1");
では、"Button1"というラベルのボタンオブジェクトを生成することを示す。
contentPane.add(b1);
では、生成されたボタンオブジェクトをコンテナオブジェクトに追加することを示す。

5. 複数のボタンが配置されたウィンドウを表示するプログラムの説明

次のプログラム MyButtonTest1.java は、GUIでよく使われるコンポーネントであるボタンが配置されたウィンドウを表示できるようにしたプログラムである。

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

class MyFrame extends JFrame
{
    Container contentPane;
    Button b1, b2, b3;
    public MyFrame(){
       Container contentPane = getContentPane();
       setTitle("My Button Application");
       setSize(300, 200);
       contentPane.setLayout(new FlowLayout());
       b1 = new Button("Button1");
       contentPane.add(b1);
       b2 = new Button("Button2");
       contentPane.add(b2);
       b3 = new Button("Button3");
       contentPane.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

プログラムの説明

b1 = new Button("Button1");
b2 = new Button("Button2");
b3 = new Button("Button3");
では、"Button1"、"Button2"、"Button3"という3つのラベルのボタンオブジェクトを生成することを示す。
contentPane.add(b1);
contentPane.add(b2);
contentPane.add(b3);
では、生成された3つのボタンオブジェクトをコンテナオブジェクトに追加することを示す。

6. イベントに対応したボタンを伴うウィンドウを表示するプログラムの説明

イベント処理の仕組み
Javaでは、イベントの発生源をイベントソースと呼ぶ。ボタンやラベルなどほとんどのコンポーネントがイベントソースとなる。一方,イベントを受け取る側をイベントリスナと呼ぶ。イベントリスナは、イベントソースからイベントを受け取り、イベントに対する処理をおこなう。Javaでは、イベントソースでイベントが発生すると、自分自身に登録されているイベントリスナにそのことを知らせ、予め定義されている処理を実行する。登録するイベントリスナは、イベントソースと、そこで発生するイベントにより異なるので、それぞれの状況に応じたイベントリスナを登録する必要がある。

イベント処理を実装する場合には、以下のような手続きを実行する。

  1. イベントソースで発生したイベントオブジェクトを、どのイベントリスナーで処理するかを定義する
  2. イベントリスナーでどのような処理をおこなうかを定義する
  3. イベントソースへのイベントリスナーを登録する

次のプログラム MyButtonTest2n.java は、ボタンが押されたことに対してイベント処理を施したプログラムである。

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

class ButtonTestFrame extends JFrame implements ActionListener 
{
    Container contentPane;
    Button b1, b2, b3;
    public ButtonTestFrame(){
       Container contentPane = getContentPane();
       setTitle("My Button Application");
       setSize(300, 200);
       addWindowListener(new MyWindowAdapter());
       contentPane.setLayout(new FlowLayout());

       b1 = new Button("Button1");
       b2 = new Button("Button2");
       b3 = new Button("Button3");

       b1.addActionListener(this);
       b2.addActionListener(this);
       b3.addActionListener(this);

       contentPane.add(b1);
       contentPane.add(b2);
       contentPane.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 JFrame 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

上のプログラム MyWinApp.java を書いて実行してみよ。実際にウィンドウを終了してみよ。
問題-2
上のプログラム MyWinApp1.java を書いて実行してみよ。さらに、ウィンドウサイズを480 x 300に変えて実行してみよ。
問題-3
上のプログラム MyWinApp1n.java を書いて実行してみよ。さらに、ウィンドウタイトルを"New Window Application"に変えて実行してみよ。
問題-4
上のプログラム MyButtonTest.java を書いて実行してみよ。さらに、GUI部品であるボタンの名前を「ボタン」に変えて実行してみよ。
問題-5
上のプログラム MyButtonTest1.java を書いて実行してみよ。さらに、GUI部品である4つのボタンを2X2の格子上に配置して表示してみよ。この場合には、setLayout(new FlowLayout());の代わりにsetLayout(new GridLayout(2,2));を使うこと。
問題-6
上のプログラム MyButtonTest2n.java を書いて実行してみよ。さらに、標準出力に表示される文字列を英語に直して表示せよ。

ソフトウエア基礎演習


nagai@rsch.tuis.ac.jp (Based upon mizutani@rsch.tuis.ac.jp's style sheet)