最終更新:2011.12.12

Frame

フレームとは、アプリケーション等を実行するための画面領域(ウィンドウ)のことです。フレームは、クラスFrameとして提供されています。このクラスはパッケージjava.awtに含まれているので、本クラスを利用するにあたってプログラムの冒頭で以下のようにimportする必要があります。


import java.awt.*;

または明示的に以下のようにしても構いません。


import java.awt.Frame;

あるいはソースコードの冒頭でimportせずに、パッケージのフルアドレスを記述しても構いません。しかし、コードが冗長になるので通常は避けた方が無難でしょう。


java.awt.Frame frame = new java.awt.Frame();

フレームを表示する

まず、フレームをインスタンス化します。


Frame frame = new Frame();

しかしこのままでは、frameという名のインスタンスを作成したに過ぎず、フレームの実体はまだ画面上に表示されません。画面にフレームを表示するには、次のようにします。


frame.setVisible(true);

次に、実際にフレームを表示するコードと実行結果の例を示します。


import java.awt.Frame;

public class awtFrame {

  public static void main(String[] args) {
    Frame frame = new Frame();
    frame.setSize(350, 150);
    frame.setVisible(true);
  }
}

java.awt.Frameサンプル画像

Frameの表示例

フレームを閉じる

アプリケーションを終了するときには、速やかにフレームを閉じなければなりません。しかし、フレームにはウィンドウを閉じるというメソッドは用意されておりません。このため、通常にウィンドウを閉じる操作を行っても、ウィンドウを閉じることはできません。この段階でウィンドウを閉じるには、コマンドを実行しているプロンプト上で[Ctrl]+[c]キーを押下する必要があります。

ではフレームを閉じるにはどうしたら良いのかというと、多くの入門書や解説サイトでは、以下のようなコードが紹介されているかと思います。


addWindowListener(
  new java.awt.WindowAdapter(){
    public void windowClosing(java.awt.event.WindowEvent e){
      System.exit(0);
    }
  }
);

ちょっとごちゃごちゃしてわかりづらいので、順を追って見ていくことにします。

メソッドaddWindowListenerFrameの親クラスであるjava.awt.Windowで定義されているメソッドで、その名の通りウィンドウ(ここではフレーム)の状態を監視する機能を追加します。
実際のメソッドは以下のように定義されています。


public void addWindowListener(WindowListener l)

メソッドaddWindowListenerの引数はインターフェイスWindowListenerです。これは、パッケージjava.awt.eventに含まれており、ソースは以下のようになっています。


package java.awt.event;

import java.util.EventListener;

public interface WindowListener extends EventListener {
    public void windowOpened(WindowEvent e);
    public void windowClosing(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);
}

WindowListenerはインターフェイスなので、implementsしたクラスで各メソッドを実装しなければなりません。以下にWindowListenerを実装したクラスWinLの例を示します。


import java.awt.event.*;

public class WinL implements WindowListener{
  
  public void windowOpened(WindowEvent e){
    System.out.println("windowOpend");
  }
  public void windowClosing(WindowEvent e){
    System.out.println("windowClosing");
  }
  public void windowClosed(WindowEvent e){
    System.out.println("windowClosed");
  }
  public void windowIconified(WindowEvent e){
    System.out.println("windowIconified");
  }
  public void windowDeiconified(WindowEvent e){
    System.out.println("windowDeiconified");
  }
  public void windowActivated(WindowEvent e){
    System.out.println("windowActivated");
  }
  public void windowDeactivated(WindowEvent e){
    System.out.println("windowDeactivated");
  }
}

上記のクラスWinLを実装したFrameの例を以下に示します。
以下のコードをコンパイル、実行してフレームを色々いじって、コンソールにどのような結果が出力されるのかを確認してください。なお、本プログラムの実行を停止するには、実行したコンソール上で[Ctrl]+[C]を押下します。


import java.lang.String;
import java.awt.Frame;

class TestFrame {
  public static void main(String[] option){
    Frame frm = new Frame();
    frm.setVisible(true);

    WinL wl = new WinL();
    frm.addWindowListener(wl);
  }
}

しかし実際のコーディングで、いちいちWindowListenerの各メソッドを実装するのは手間がかかります。このため、あらかじめこのインターフェイスを実装した抽象クラスWindowAdapterが用意されています。
以下に、WindowAdapterのソースを示します。


package java.awt.event;
public abstract class WindowAdapter
    implements WindowListener, WindowStateListener, WindowFocusListener
{
    public void windowOpened(WindowEvent e) {}
    public void windowClosing(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 void windowStateChanged(WindowEvent e) {}
    public void windowGainedFocus(WindowEvent e) {}
    public void windowLostFocus(WindowEvent e) {}
}

抽象クラスWindowAdapterを利用すれば必要なメソッドだけをオーバーライドすれば良く、手間が省けます。

以上を踏まえた上で、改めて先ほどのウィンドウを閉じる処理を見てみます。


1: addWindowListener(
2:   new java.awt.WindowAdapter(){
3:     public void windowClosing(java.awt.event.WindowEvent e){
4:       System.exit(0);
5:     }
6:   }
7: );
  1. メソッドaddWindowListener()により、フレームにウィンドウの状態を監視する機能を組み込みます。
  2. メソッドaddWindowListener()は、引数にインターフェイスWindowListener(実際にはWindowListenerを実装したクラス)を要求します。しかし、前述のようにインターフェイスのすべてのメソッドを実装するのは手間がかかるので、既に実装されている抽象クラスWindowAdapterを引数に与えます。引数に与えるWindowAdapterはそのままでは利用できないので、new宣言によりインスタンス化します。
  3. ここで行いたいのはウィンドウを閉じることなので、メソッドwindowClosing()のみをオーバーライドします。
  4. Java仮想マシンの終了を意味するSystem.exit()でメソッドをオーバーライドします。メソッドの引数に与えている数字は、プログラム終了時にOSへ渡される数値です。数値は自由に決められますが、一般的には“0”が正常終了を表すことが多いようです。

実際の処理過程で見ていくと順序は逆になり、以下の通りとなります。

  1. 抽象クラスWindowAdapterのメソッドwindowClosing()をオーバーライドし、インスタンス化します。
  2. インスタンス化したクラスWindowAdapterを引数に、ウィンドウオブジェクト(ここではクラスFrame)にメソッドaddWindowListener()によりWindowListenerを追加します。

以上で仕組みはわかりましたが、個人的にこのコードは非常に可読性が低いと感じております。ですので、色々と試した結果、以下のようなコードに落ち着きました。


import java.lang.String;
import java.awt.Frame;

class TestFrame {
  public static void main(String[] option){
    Frame frm = new Frame();
    frm.setVisible(true);
    WinAdapter wa = new WinAdapter();
    frm.addWindowListener(wa);
  }

  public class WinAdapter extends WindowAdapter{
    public void windowClosing(WindowEvent close){
      dispose();
    }
  }
}

終了処理にはSystem.exit()ではなくdispose()を使っています。System.exit()はJava仮想マシンの終了を意味しますが、dispose()はメソッド呼び出し元のウィンドウおよび、そこから呼び出されているすべてのコンポーネントを解放し、メモリ資源をOSへと返却します。ここで行いたいのはJava仮想マシンの終了ではなくFrameを閉じることなので、dispose()を使うのが作法的にも正解です。

クラスの内部でさらにクラスを定義していることに注意してください。ここで、先ほどのクラスWinLのようにメソッドwindowClosing()をオーバーライドしたクラスを用意してフレームを表示するクラスから呼び出そうとしても、コンパイルエラーとなります。なぜなら、メソッドdispose()は抽象クラスWindowAdapterおよびその親クラスには実装されていないからです。メソッドdispose()が実装されているのは、Frameの親クラスであるjava.awt.Windowとなります。

戻る