戻る

グラフィックス:フレームの作成

クラスJFrame

   グラフィックスを使ったアプリケーションでは、どれもウィンドウを持っている。
  そして、その中に必要なグラフィックスを描いたり、ユーザーインターフェースとなる部品を置いている。
   X Window Systemでは、このアプリケーションの基本となるウィンドウをトップレベルウィンドウと言っているが、javaの用語ではフレームと言う。
  したがって、どのグラフィックスを使ったアプリケーションも、まずはフレームの作成から取りかからなければならない。
   今回は、グラフィックス用のライブラリとしてSwingを利用する。Swingでフレームを作るにはJFrameというクラスを使う。
  ただし、クラスJFrameのインスタンスを直接生成することはしない。

   JFrame f = new JFrame( ); ・・・・・これはしない

   代わりにJFrameを継承した子クラスを作る。そのクラスにアプリケーション固有のカスタマイズを施す。
  そして、そのインスタンスを生成する事でフレームを作るのである。

   class AppFrame extemds JFrame { ・・・・・JFrameを継承
     … ・・・・・必要なメンバーを記述
     …
   }

   AppFrame frame = new AppFrame( ); ・・・・・インスタンスを生成する

   以後、フレームの為のクラスをフレームクラスと呼ぶ。

フレームのサイズ

   JFrameの子クラスのインスタンスを生成しても、それだけではフレームは表示されない。
  showをいうメソッドを呼び出して初めてフレームが表示される。

   AppFrame frame = new AppFrame( ); ・・・・・インスタンスを生成し
   frame.show( ); ・・・・・showメソッドを実行する

   ただし、これだけでもまだ不足である。それは、デフォルトのフレームサイズがゼロになっているからである。
  そこで、フレームのサイズを大きくする必要がある。その為にはsetSizeというメソッドを使う。

   frame.setSize(400,300);

   setSizeの2つの引数は、横と縦のサイズをピクセル単位で指定する。
  たとえば、上記のようなコードを書けば、400×300のサイズのフレームが作られる。

フレームの表示

   ここまでをまとめると、フレームの作成に必要なコードは次の3つである。

   AppFrame frame = new AppFrame( ); ・・・・・インスタンスを生成し
   frame.setSize(400,300); ・・・・・サイズを設定し
   frame.show( ); ・・・・・showメソッドを実行する

   このようにしても良いのだが、通常setSizeはフレームクラスのコンストラクタの中に置かれる事が多い。

   class AppFrame extends JFrame {
    public AppFrame( ) { ・・・・・コンストラクタ
     setSize(400,300) ; ・・・・・ここに置く
    }
   }

   つまり、フレームクラスのインスタンスを生成した段階で、すでにサイズの設定は終わっているというようにするのである。
  したがって、アプリケーションのmainメソッドは、次のような単純なものになる。

   public static void main(String[ ] args)
   {
    AppFrame frame = new AppFrame( );
    frame.show( );
   }

   後のアプリケーション固有の処理は、フレームクラスが処理してくれる。(ようにプログラムする)

   以上をテストする為のサンプルアプリケーションを以下に示す。
  このアプリケーションは、ただフレームを表示するだけである。しかし、全てのグラフィックスアプリケーションの基礎になる。

   サンプル:Frame.java

   //
   //Frame.java---フレームを作る
   //
   import javax.swing.*;

   class AppFrame extemds JFrame {
    public AppFrame( ) {
     setSize(400,300);
    }
   }

   public class Frame
   {
    public static void main(String[ ] args)
    {
     AppFrame frame = new AppFrame( );
     frame.show( ):
    }
   }

   ここで注意したいのが、タイトルバーやフレームを囲む境界線などの装飾である。これらはフレームではない。
  これらの装飾は、プラットホームにより異なるが、X Window Systemの場合はウィンドウマネージャが描いている。
  したがって、ウィンドウマネージャを交換すると(X Window Systemはウィンドウマネージャを自由に交換できる)違った見栄えになる。

グラフィックス:クローズ可能なフレーム

   上記で作成したフレームは、少し問題がある。
  その症状はプラットホームにより異なるが、要するに通常の方法ではクローズ出来ない。例えば、メニューなどを使ってフレームをクローズする。
  その結果、確かにフレームは消える。しかし、ウィンドウは消えてもプロセスは残っている。
  実際、pstreeコマンドで調べてみると、javaコマンドが残っているのが分かる。

   $ pstree
   init-+-atd
    |-bash---xinit-+-XF86_S3
    |         `-fvwm2-+-Fvwm\Auto
    |               |-FvwmCommands
    |               |-FvmPager
    |               |-Kinput2
    |               |-kterm---bash-+-java ・・・・・ここ
    |               |          `pstree
    |               |-mule
      …
      …
   $ _

   あるいはpsコマンドで確かめる事もできる。

   $ ps -a
   PID TTY     TIME CMD
   204 tty1   00:00:00 xinit
   208 tty1   00:00:02 fvwm2
     …
     …
   894 ttyp0  00:00:08 java ・・・・・残っている
   920 ttyp0  00:00:00 ps
   $ _

   javaのアプリケーションを完全に終了させるには、そのプロセスをkillすればよい。

   $ kill 253
   [1]+ 終了しました   java Frame
   $ _

   しかし、ただウィンドウをクローズしただけでは、アプリケーションは終了しない。
  これでは不便なので、少しコードを追加してウィンドウをクローズするだけで、アプリケーションを終了できるようにする。
  そのためには、フレームクラスのコンストラクタに次のコードを追加する。

   addWindowListener(
    new WindowAdapter( ) {
     public void windowClosing(WindowEvent e) {
      Sustem.exit(0);
   }}};

   なお、このコードの中に出てくるWindowAdapterを使うには次のimport文が必要である。

   import java.awt.event.*;

   次のサンプルアプリケーションは、前項のプログラムに上記コードを追加して、
  ウィンドウをクローズするだけでアプリケーションを終了できるようにしたものである。

   サンプル:CloseFrame.java

   //
   //CloseFrame.java---クローズ可能なフレーム
   //
   import javax.seinf.*;
   import java.awt.event.*;

   class AppFrame extends JFrame {
    public AppFrame( ) {
     setSize(400,300);

     addWindowAdapter( ) {
      public void windowClosing(WindowEvent e) {
       System.exit(0);
     }}};
    }
   }

   public class CloseFrame
   {
    public static void main(string[ ] aegs)
    {
     AppFrame feame = new AppFrame( );
     frame.show( );
    }
   }

   実行すると、まだフレームを表示するだけのアプリケーションなので、見かけは前項のものと同じである。

グラフィックス:タイトル

   次にタイトルバーに任意のタイトルを表示する。そのためには、setTitleというメソッドを使う。

   setTitle("GUI Application"); ←ここにタイトルに表示する文字列を指定する。

   このコードをフレームクラスのコンストラクタに置く。
  例えば、以下のサンプルアプリケーションは、前項のプログラムに上記のコードを追加したものである。

   サンプル:Title.java

   //
   //Title.java---タイトルの表示
   //
   import javax.swing.*;
   import java awt.event.*;

   class AppFrame extends JFrame {
    public AppFrame( ) {
     setTitle("GUI Application") ; //タイトルバーの設定
     setSize(400,300);

     addWindowAdapter( ) {
      new WindowAdapter( ) {
       public void windowClosing(WindoeEvent e) {
        System.exit(0);
     }}};
    }
   }

   public class Title
   {
    public static vid main(String[ ] args)
    {
     AppFrame = new AppFrame( );
     frame.show( );
    }
   }

   以上を実行すると、タイトルバーに指定した文字列が表示されている。

グラフィックス:コンテントペーン

   前項までのプログラムでフレームを作成し、タイトルを表示するところまで進んだ。
  次はいよいよフレーム内部にコンポーネントを配置していく。
  コンポ-ネントというのは、ボタンとかテキストフィールドといったGUI部品のことである。
   コンポーネントの配置には少し手続きが必要である。しばらくはコードを追加しても画面上の変化は見られない。
  少々退屈な話が続くが、グラフィックスを使うためには避けては通れない。
   まずはコンテントペーンの配置である。ここでは、コンポーネントとしてSwingライブラリによるコンポーネントを使用する。
  Swingコンポーネントを直接フレームの上に配置する事はできない。
  フレームの上にコンテントペーンを置き、その上にコンポーネントを配置する。

   コンテントペーンを作るには、フレームクラスのgetContentPaneメソッドを実行する。そして、それをContainer型の変数で受取る。

   Container cp = getContentPane( );

   ここで、Container型の変数は、後でコンテントペーンにコンポーネントを配置する時に使われる。
  このコードをフレームクラスのコンストラクタに置けばよい。なお、Container型を使うには、次のimport文が必要である。

   omport java.awt.*;

   次は、前項のサンプルにコンテントペーンの配置を追加したものである。

   サンプル:Pane.java

   //
   //Pane.java---コンテントペーン
   //
   import javax.swing.*;
   import java.awt.event.*;
   import java.awt.*;

   class AppFrame extends JFrame {
    public AppFrame( ) {
     setTitle("ContentPane Test") {
     setSize(400,300);

     addWindowListener(
      new WinsowAdapter( ) {
       public void windowClosing(WindowEvent e) {
        Sustem.exit(0);
     }});

     Container cp = getContentPane( );
    }
   }

   public class Pane
   {
    Public static void main(String[ ] args)
    {
     AppFrame frame = new AppFrame( );
     frame.show( );
    }
   }

   このサンプルを実行しても、タイトル以外は前項のフレームと同じである。

グラフィックス:ボタン

   前項のアプリケーションでは、フレームにコンテントペーンを配置した。
  コンテントペーンがあると、その上にSwingのコンポーネントを乗せる事が出来る。ここでは、手始めとしてボタンを配置する。

JButton

   ボタンを作るにはJButtonクラスを使い、そのインスタンスを生成する。

   JButton bt;
   bt = new JButton("Exit");

   ここでJButtonのコンストラクタに渡す引数は、ボタンの表面に表示するラベルである。

   bt = new JButton("Exit"); ←このラベルがボタンの表面に表示される。

   そして、このボタンのインスタンスをコンテントペーンのaddメソッドを使ってコンテントペーンの上に配置する。

   bt = new JButton("Exit"); ・・・・・btはボタン
   cp.add(bt); ・・・・・・・・・・・・・・・・・cpはコンテントペーン

   あるいは、この2行を次の1行にまとめてもよい。

   cp.add(bt = new JButton("Exit"));

JButton変数の位置

   ところでボタンのインスタンスを指す変数は、フレームクラスのコンストラクタには置かない。

   class AppFrame extends JFrame { ・・・・・フレームクラス
    public AppFrame( ) { ・・・・・・・・・・・・・・・コンストラクタ
      …
      …
     Continer cp = getContentPane( );
     private JButton bt; ・・・・・・・・・・・・・・ここには置かない
     cp.add(bt = new JButton("Exit");
    }
   }

   代わりにフレームクラスのフィールドにする。

   class AppFrame extends JFrame {
    JButton bt; ・・・・・・・・・・・・・・・・・・ここに置く

    public AppFrame( ) {
      …
      …
     Container cp = getContentPane( );
     cp.add(bt = new JButton("Exit"));
    }
   ]

   これは。後でボタンが押されたときの処理を書くときに他のメソッドでbtを参照できるようにするためである。
  btは、クラスの外から参照させる必要は無いのでprivateフィールドにする。

   class AppFrame extends JFrame {
    private JButton bt; ・・・・・・・・・・・・privateフィールド
      …
      …
    public AppFrame( ) {
     Container cp = getContentPane( );
     cp.add(bt = new JButton("Exit");
    }
   }

   以上でボタンをコンテントペーンの上に配置できる。ここまでをテストする為のサンプルアプリケーションを次に示す。

   サンプル:Button.java

   //
   //Button.java---ボタンを作る
   //

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

   class AppFrame extends JFrame {
    private JButton bt;

    public AppFrame8 ) {
     setTitle("Button Test");
     setSixe(400,300);

     addWindowListener(
      new WindowAdapter( ) {
       public void windowClosing(WindowEvent e9 {
        System.exit(0);
     }});

     Container cp = getContentPane( );
     cp.add(bt = new JButton("Exit");
    }
   }

   public class Button
   {
    public static void main(String[ ] args)
    {
     AppFrame frame = new AppFrame( );
     frame.show( );
    }
   }

   このサンプルを実行すると、ウィンドウ(フレーム)の中央にExitの文字とそれを囲む枠が表示されている。
  しかし、この小さな枠がボタンなのではない。
  枠は、今ボタンにフォーカスがあることを示しているのに過ぎない。また、文字のExitはボタンのラベルに過ぎない。
   実は、ウィンドウ(フレーム)全体がボタンになっているのである。
   ためしにウィンドウ(フレーム)内のどこでもいいのでクリックしてみると、ボタンが押されフレームの色が変わる。

   さらにウィンドウ(フレーム)のサイズをいくら変更しても、ボタンのサイズがフレームいっぱいに拡大・縮小される。
   このように上記のようにしてボタンを作ると、ボタンがフレームいっぱいに広がってしまう。
  これは、コンテントペーンのデフォルトのレイアウトマネージャがそうなっているがらである。
  コンポーネントの配置を制御するには、レイアウトマネージャについて知る必要がある。それを、次のところで説明する。

グラフィックス:ボーダーレイアウト

   javaでは、コンポーネントの配置をレイアウトマネージャが管理している。
  レイアウトマネージャにはいくつかの種類があって、使用するレイアウトマネージャにより、コンポーネントの並べ方が変わる。

ボーダーレイアウトの配置

   前項のサンプルアプリケーションでは、ボタンをコンテントペーンの上に配置したl
  コンテントペーンのデフォルトのレイアウトマネージャは、ボーダーレイアウトである。
   ボーダーレイアウトは、コンポーネントの位置を上下左右中央の5種類から選択する事が出来る。
  ただし、位置を指定するのに上下左右中央という用語は使わず、
  英語で、North(上)・East(右)・South(下)・West(左)・Center(中央)、と指定する。位置を選択しないと、Centerが指定されたことになる。

コンポーネントの拡大

   ボーダーレイアウトで配置されたコンポーネントは、指定された位置で目いっぱいに拡大されて配置される。
  ここが、他のレイアウトマネージャと異なる。ボーダーレイアウトは、次の順序でコンポーネントを配置していく。

  1: まず、North、Southが指定されたコンポーネントがあれば、それらを上下の指定された位置に配置する。
    このとき、それらのコンポーネントは、フレーム幅いっぱいに拡大される。
  2: 次にWest、Eastが指定されたコンポーネントがあれば、それらを左右の指定された位置に配置する。
    このとき、それらのコンポーネントは、残りの高さ幅いっぱいに拡大される。
  3: 最後にCenter、または無指定のコンポーネントがあれば、それを残された中央の領域いっぱいに拡大して配置する。

   もし、同じ位置(例えばWest)を重複して指定すると、後から配置されたコンポーネントが先に配置されたコンポーネント;の上に乗っかる。
  このため先に配置されていたコンポーネントは隠されてしまう。
   前項のサンプルアプリケーションでは、ボタンを無指定で配置した。
  このためCenterが指定されたものとして扱われ、
  中央いっぱい(この場合、他のコンポーネントが無いので、フレームいっぱい)に拡大されて配置された。
  これが前章のアプリケーションでボタンがフレームいっぱいに拡大された理由であるl。

位置の指定

   ボーダーレイアウトでコンポーネントを配置する位置を指定するには、addメソッドの第引数を使う。
  例えばボタンbtをコンテントペーンcpの左側に配置するには、次のようにする。

   cp.add(bt, "West");

   以上をテストする為のサンプルアプリケーションを次に示す。
  このアプリケーションでは、5つのボタンを生成し、それをボーダーレイアウトで5箇所に配置している。

   サンプル:Border.java

   //
   //Border.java---ボーダーレイアウト
   //

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

   class AppFrame extends JFrame {
    private JButton b1;
    private JButton b2;
    private JButton B3;
    private JButton b4;
    privatr JButton b5;

    public AppFrame( ) {
     setTitle("BorderLayout Test");
     setSixe(400,300);

     addWindowListener(
      new WindowAdapter( ) {
       public void windowClosing(WindowEvent e) {
        System,exit(0);
     }});

     b1 = new JButton("Sunday");
     b2 = new JButton("Monday");
     b3 = new JButton("Tuesday");
     b4 = new JButton("Wednesday");
     b5 = new JButton ("Thursday");

     Container cp = getContentPane8 );
     cp.add(b1);
     cp.add(b2,"West");
     cp.add(b3,"East");
     cp.add(b4,"North");
     cp.add(b5,"South");
    }
   }

   public class Border
   {
    public static void main(String[ ] args)
    {
     AppFrame frame = new AppFrame8 );
     frame.show( );
    }
   }

   実行すると、コンポーネントが上下、左右。中央の順に配置されている事に注意。
  Sundayボタンは、位置を指定していないので、”Center"が指定されたものとみなされ、中央に配置されている。

グラフィックス:フローレイアウト

   コンテントペーンのデフォルトのレイアウトマネージャであるボーダーレイアウトは、
  コンポーネントを本来のサイズではなく、フレームいっぱいに拡大してしまう。このため。通常のコンポーネントの配置には向いていない。
   では、ボーダーレイアウトは何に使われるのかというと、後から出てくるパネルなどのコンテナの配置に使われるのが一般的である。
  本節では、コンポーネントを本来のサイズで配置するレイアウトマネージャの中から、最も基本的なフローレイアウトについて説明する。

レイアウトマネージャの変更

   SetLayoutメソッドを使うと、デフォルトのレイアウトマネージャを他のものに変更することができる。

   Container cp = getContentPane( ); ・・・cpはコンテントペーン
   cp.setLayout(・・・・・); ・・・・・・・・・・・・・・cpのレイアウトマネージャを変更する

   SetLayoutメソッドの引数は、変更するレイアウトマネージャのインスタンスである。例えば、フローレイアウトに変更するなら次のようにする。

   FlowLayout f = new FlowLayout(・・・・);
   cp.setLayout(f);

   あるいは、この2行を次のように1行にまとめてもよい。

   cp.setLayout(new FlowLayout(・・・・・));

   FlowLayoutのコンストラクタの引数には、コンポーネントをどのように配置するかを指定する。これは、次の4つのうちいずれかを選択する。

引数    配置   
FlowLayout.LEFT 左寄せ
FlowLayout.RIGHT 右寄せ
FlowLayout.CENTER 中央寄せ

   たとえば、コンポーネントを左寄せで配置していくには次のようにする。

   cp.setLayout(new FlowLayout(FlowLayout.LEFT));

   前章のサンプルアプリケーションで、コンテントペーンのレイアウトマネージャをフローレイアウトに変更したものを示す。

   サンプル:Flow.java

   //
   //Flow.java---フローレイアウト
   //

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

   class AppFrame extends JFrame {
    private JButton b1;
    private JButton b2;
    private JButton b3;
    private JButton b4;
    private JButton b5;

    public AppFrame( ) {
     setTitle("FlowLayout Test");
     setSixe(400,300);

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

     b1 = new JButton("Sunday");
     b2 = new JButton("Monday");
     b3 = new JButton("Tuesday");
     b4 = new JButton("Wednesday");
     b5 = new JButton("Thursday");

     Container cp = getContentPane( );
     cp.setLayout(new FlowLayout(FlowLayout.LEFT));

     cp.add(b1);
     cp.add(b2,"West");
     cp.add(b3,"East");
     cp.add(b4,"North");
     cp.add(b5,"South");
    }
   }

   punlic class Flow
   }
    public static void main(Strinf[ ] args)
    {
     AppFrame frame = new AppFrame( );
    }
   }

   実行すると、ボタンが本来のサイズで配置されているのがわかる。
  このフローレイアウトでは、FlowLayout.LEFTを指定したので、コンポーネントが左寄せになっている。
  フローレイアウトの左寄せでは、次のように配置される。

  1: できるだけコンポーネントを左から配置していく。
  2: その行に収まらなくなったら次の行の左側に配置する。

   たとえば、3つのボタンを配置した段階でその行がいっぱいになったら、次の4つ目のボタンから次の行に配置される。
   フレームのサイズを変更すると、ボタンの配置が変わる。
  例えば、横幅をもう少し広げれば、最初の4つのボタンが同じ行に表示されるようになる。

   フローレイアウトのコンストラクタにFlowLayout,RIGHTを指定すると、右寄せになる。

   cp.setLayout(new FlowLayout(FlowLayout.RIGHT)); ←ここ

   また、フローレイアウトのコンストラクタにFlowLayOut.CENTERを指定すると、中央寄せになる。

   cp.setLayout(new FlowLayout(FlowLayout.Center));




次へ