オブジェクト指向プログラミングb 第10回


●GUI前編「もっとJavaを学ぶ 第7回 (2004年3月 )」

 多くのプログラミング言語では,グラフィカル・ユーザ・インタフェイス(GUI)に関する
機能は言語規格には含まれていません。しかし,JavaにはGUI機能が言語の機能として用意
されています。今回から2回にわたって,JavaのGUI機能について解説します。

【JavaとGUI】
 私たちが日常的に使用しているソフトウェアの多くは,ウィンドウを持ち,その中にボ
タンやメニューなどがついています。そのボタンをマウスのポインタでクリックする(つま
り"ボタンを押す")などして,インタラクティブにソフトウェアを動作させていきます。
 このようなウィンドウやボタン,マウスによるクリックといったグラフィカルなユーザイ
ンタフェイスを,グラフィカル・ユーザ・インタフェイス(Graphical User Interface),略
してGUIと呼びます。
 多くのプログラミング言語は,言語としての規格が定められています。しかし,そうし
た正式の規格の中にGUIの機能を含んでいるプログラミング言語は少数派です。たとえば,
C言語,C++,Fortranといった言語には,GUIに関する規格は含まれていません。これは,
GUIの機能自体が,プラットフォームに強く依存してしまうため,ということが大きな理
由の一つです。
 しかし,Javaはプラットフォームに依存しない言語として設計されており,GUI機能も
またプラットフォームに依存しない形で,標準のクラスライブラリに含まれているのです。
 JavaのGUI機能は比較的簡単に利用することができますし,なによりプラットフォーム
に依存せずにGUIつきのソフトウェアを開発できることは大きな利点です。

【AWTとSwing】
 Javaには最初のバージョン(JDK 1.0)からGUI機能が用意されていました。それが,AWT
(Abstract Window Toolkit)
です。AWTは,java.awtパッケージとしてまとめられています。
 しかし,AWTで用意されたGUI機能は,それほど高機能ではなく,効率が悪かった部分も
ありました。そこで,JDK 1.2 (いわゆるJava 2)にバージョンアップしたとき,Swingとい
う高機能で効率的なGUIクラスライブラリが導入されました。Swingは,javax.swingという
標準パッケージとして用意されています。
 しかし,SwingはAWTを完全に置き換えるものではありません。SwingはAWTの中核部分
を利用しながら,AWTの一部の機能に対してより改良された代替機能を提供し,また新たな
新機能を追加するものです
。つまり,AWTはSwingが導入された現在も残されており,AWT
とSwingは共存する形になっています
。AWTとSwingを合わせて,JFC(Java Foundation
Class)
と呼びます。
 Swing自体がAWTの機能を利用しているので,AWTの機能をまったく使わずにSwingの機
能だけでGUIソフトウェアを作成することは難しいですし,逆にAWTだけでGUIソフトウェア
を作成すると,ソフトウェアの実行効率が悪くなるだけでなく,高機能なGUI機能を享受する
ことができなくなります。
 ですから,JavaのGUI機能を学習するときは,AWTとSwingの両方の基礎を学ばなければ
なりません。そして実際にGUI機能を使うときには,AWTを使わざるを得ない部分はしかた
ないとして,Swingに代替機能があればできるだけSwingの機能を使うべきでしょう。

【AWTの基本ウィンドウ】
 では,GUIプログラミングの学習を本格的に始めることにしましょう。最も基本的なGUI
プログラムとして,ウィンドウを表示するプログラムを見てみましょう。まず,AWTを使
った場合を,List 1に示します。
List 1 AWTWindows.java


 最初に,List 1-<①>でjava.awtパッケージをインポートしています。mainメソッドの中
のList 1-<2>では,Frame型のオブジェクトfを生成しています。このFrameが,標準的な
ウィンドウを表すクラスなのです。コンストラクタの呼び出しは
  Frame( "Hello AWT Frame" );
となっていますが,この文字列は,ウィンドウのタイトルに使われます。
 List 1-<3>では
  f.setSize( 200, 100 );
としています。setSize()メソッドは,ウィンドウのサイズ(横幅と縦幅)をpixel単位で設定
するメソッドです。ここでは,ウィンドウのサイズを横200pixel,縦100pixelとしていま
す。List 1-<4>は
  f.setVisible( true );
となっています。setVisible()メソッドは,ウィンドウの可視・不可視を設定します。ウィ
ンドウは生成された段階では見えない状態になっているの
で,setVisible()メソッドにtrue
を渡すことで,ウィンドウfを見える状態にしているのです。
 List 1を実行すると,Fig.1のように,横200pixel,縦100pixelの標準的なウィンドウが
表示されるはずです。

●Frame型ウィンドウ
 Fig.1に示すように,このFrame型ウィンドウは標準的に使われるウィンドウで,タイト
ルバー
が一番上についています。タイトルバーには,タイトルの文字列"Hello AWT Frame"
の他に,ウィンドウを閉じるクローズボックス(MacOS Xでは一番左の丸,Windows XPで
は一番右の×印のある四角)などがついています。また,Windows XPでの実行例のように,
ウィンドウの周りにボーダ(縁)がついている場合もあります。このFrame型ウィンドウの場
合,setSize()メソッドで設定したサイズは,タイトルバーやボーダを含んだサイズである

とに注意しておいてください。
 ところで,List 1を実行して表示されたFrame型ウィンドウのクローズボックスをクリッ
クしてもプログラムは終了しません。終了させるには,このプログラムを動かすためにjava
コマンドを実行したコンソールで,Control+c(コントロールを押しながらCのキー)を押して
下さい。

●Window型ウィンドウ
 それでは,次にList 1-<5>のコメントアウトされている部分を有効にしてみましょう。
List 1-<5>の部分では,
  Window w = new Window( f );
  w.setSize( 50, 50 );
  w.setVisible( true );
となっていて,List 1-<2>〜<4>とほとんど同じ形をしています。違いはFrameではなく,
Windows型のウィンドウを生成しようとしているところです。List 1-<5>を有効にして
List 1を実行すると,Fig.2のような,タイトルバーもボーダも無いウィンドウが表示され
ることがわかります。これが,Window型ウィンドウなのです。
 Window型ウィンドウがタイトルバーもボーダも持たないのは,自由にウィンドウの中
身をカスタマイズして使用できるようにするため
です。また,Window型ウィンドウは,
サブウィンドウとして他のFrame型ウィンドウまたはWindow型ウィンドウに所有される
ようになっています。つまり,所有主(オーナー)をたどっていくと,結局は1個のFrame
型ウィンドウにたどり着くことになります。
 List 1-<5>のWindowのコンストラクタの呼び出し部分は
  Window( f )
となっていますね。これは,このWindow型ウィンドウwのオーナーとしてFrame型ウィン
ドウfを指定しているのです。

●Dialog型ウィンドウ
 今度はさらに,List 1-<6>の部分を有効にしてみましょう。List 1-<6>の部分は
  Dialog d = new
   Dialog( f, "Hello AWT Dialog" );
  d.setSize( 100, 75 );
  d.setVisible( true );
となっています。List 1-<2>〜<4>との違いは,Dialog型ウィンドウを生成しているとこ
ろです。
 このDialog型ウィンドウは,いわゆるダイアログウィンドウのために用意されたウィン
ドウ
なのです。ダイアログウィンドウは,ソフトウェアのユーザと特定の目的で限定的な
会話(dialog)を行うためのウィンドウです。よく使われるのは,ファイルを保存するとき
に表示されるファイル保存ダイアログなどがあります。List 1-<6>を有効にしてList 1を
実行すると,Fig.3のようにダイアログウィンドウが表示されるのがわかります。Frame型
ウィンドウとほぼ同じですが,タイトルバーについてくるボタンの数や状態などが異なる
ことがわかります。
 Dialog型ウィンドウも,他のウィンドウのサブウィンドウとして利用されるので,オー
ナーを指定する必要があります。List 1-<6>のDialogのコンストラクタ呼び出しで,最初
にfを渡しているのは,fをオーナーに指定しているのです。

【Swingの基本ウィンドウ】
 では,次にSwingの基本的なウィンドウを見てみましょう。SwingにはJFrameJWindow
JDialogという,AWTのFrame,Window,Dialogの改良版があります。Swingでは,AWT
のクラスを改良したクラスに対して,JFCの頭文字のJをつけて区別しているのです
Swing
の機能を使う場合には,必ずSwingの基本ウィンドウを使うようにしてください

 List 1をSwingを使って書き換えたのが,List 2です。List 2-<①>では,javax.swingパッ
ケージをインポートしています。
List 2 SwingWindows.java


●JFrame型ウィンドウ
 List 2-<2>〜<4>は,List 1-<2>〜<4>に相当する部分で,List 1がFrame型ウィンドウ
を生成・表示していたのに対して,List 2-<2>〜<4>では,JFrame型ウィンドウを生成・
表示しています。
 List 2を実行すると,Frame型ウィンドウ(Fig.1)と全く同じように,タイトルバーを持つ
(OSによってはボーダを含む)標準的なウィンドウが表示されます。ちょっとした違いとして
は,Swingのウィンドウでは,タイトルバーにあるクローズボックスをクリックすると,ウィ
ンドウが閉じる
ことです。実際に確かめてみてください。

●JWindos型ウィンドウ
 List 2-<5>は,List 1-<5>に相当するところで,List 1-<5>がWindow型ウィンドウを生
成・表示していたのに対し,List 2-<5>ではJWindow型ウィンドウを生成・表示しています。
List 2-<5>の部分を有効にしてList 2を実行すると,Fig.2のWindow型ウィンドウの外観と
同じように,空白のJWindow型ウィンドウが表示されます。
 WindowとJWindowのちょっとした違いとしては,Windowがサブウィンドウ用のために
オーナーを指定しなければならないのに対して,JWindowはメインウィンドウとしても使え
るようになたっためにオーナーを指定しなくても生成できることがあげられます。List 2-<5>
でも,オーナーを指定せずにJWindow型オブジェクトwを生成しています。

●JDialog型ウィンドウ
 List 2-<6>は,List 1-<6>に相当します。List 1-<6>がDialog型ウィンドウを生成・表示
していたのに対し,List 2-<6>ではJDialog型ウィンドウを表示・生成しています。List 2-<6>
を有効にしてList 2を実行すると,Fig.3のDialog型ウィンドウと同じ外観のJDialog型ウィン
ドウが表示されます。

【コンポーネントとコンテナ】
 List 1とList 2は,ウィンドウを表示するだけでしたが,それだけではつまらないですね。
そこで,ボタンやポップアップメニューなどの“GUI部品”をウィンドウに追加してみましょう。
 なお,JavaではウィンドウやボタンのようにGUI上でユーザとやりとりをするための“部品”
を,コンポーネント(component)と呼びます。また,ウィンドウのように,他のコンポーネ
ントを含むことができる特殊なコンポーネントを,コンテナ(container)と言います。英語で
containerとは,“入れ物”という意味です。

【AWTのコンポーネント】
 では,AWTを使って,Frame型ウィンドウというコンテナに,ボタンなどのコンポーネ
ントを“入れて”みましょう。List 3を見て下さい。このプログラムを実行すると,Fig.4
のように,ボタンをはじめとする多数のコンポーネントを配置したウィンドウが表示され
ます。List 3自体は,それほど複雑なプログラムではありませんね。このように,Javaで
は簡単にGUI部品をウィンドウに追加することができるのです。
List 3 AWTComponents.java

 では,List 3を見ていきましょう。List 3-<①>では,java.awtパッケージをインポートし
ています。List 2-<2>では大きさ横280pixel,縦250pixelのFrame型ウィンドウfを生成し
ています。次にいよいよ,このコンテナfにいろいろなコンポーネントを追加していきます。

●レイアウトマネージャによる配置
 ここで,コンポーネントをコンテナに配置する方法を考えてみましょう。素直に考える
と,“コンテナ上の座標を指定して,その位置にコンポーネントを置ければよい”,とい
うことになるでしょう。実際,コンポーネントには
  setLocation(int x, int y)
というメソッドが用意されていて,コンポーネントをコンテナ上の位置(x, y)に置くことが
可能です。
 しかし,ことはそう単純ではないのです。Fig.4をよく見てみて下さい。Fig.4-(1)はMacOS X 10.3
での実行例,Fig.4-(2)はWindows XPでの実行例です。この2つの実行例を比較すると,
GUI部品の大きさや形が,プラットフォームによって異なることがわかります。たとえば,
同じボタンにしても,MacOS Xのボタンの方が,Windows XPのボタンよりも横長です。
また,Fig.1の例からもわかるとおり,同じ大きさのFrame型/JFrame型ウィンドウでも,
ボーダの有無によって,実際にコンポーネントを配置できる領域の大きさが異なったりす
るわけです。

 このように,コンポーネントの外形は,プラットフォームによって異なります。そのため,
Javaではコンポーネントを使うとき,単純にコンテナ上の具体的な座標を指定してコンポー
ネントを配置するのはあまり良い方法とは言えないのです。
 たとえば,Windows XP上でボタンを綺麗に配置したつもりでも,同じプログラムをMacOS X
上で動かしたときには,ボタンどうしが重なるなどしてレイアウトが崩れてしまう可能性が
あるわけです。逆に,MacOS Xで綺麗にボタンを配置したつもりでも,Windows XPでは,
ボタンの一部がボーダに隠されてしまうことも起こりえます。
 そこで,通常のJavaプログラミングでは,コンポーネントをコンテナに配置するときに,
配置位置の座標を具体的に指定することはしません。そのかわり,レイアウトマネージャ
という機能を使います。
 Javaには,それぞれ異なったコンポーネントの配置方針を持つレイアウトマネージャが,
標準で数種類用意されています。プログラマは,まず,使用したいレイアウトマネージャ
を選んで,コンテナにセットしておきます
。コンテナへのレイアウトマネージャのセット
は,コンテナに用意されているsetLayout()メソッドを使います。
 そしてプログラマは,コンテナに用意されているadd()メソッドで,コンテナにコンポー
ネントを“追加”するだけ
です。そして,追加されたコンポーネントの配置は,コンテナに
セットされたレイアウトマネージャが実行する
のです。レイアウトマネージャは自分のレイ
アウト指針に基づいて,(実行プラットフォームの事情を配慮しながら)コンポーネントを自
動的に綺麗に配置してくれます。
 List 3は,レイアウトマネージャを使用してコンポーネントを配置しています。そのおか
げで,Fig.4に示すように,異なるプラットフォームでも同じようにコンポーネントを綺麗
に配置できるのです。
 コンテナにはデフォルトのレイアウトマネージャが用意されています。Frame,JFrame,
Window,JWindow,Dialog,JDialogのデフォルトレイアウトマネージャは,ボーダレイ
アウト(BorderLayout)
と呼ばれるものです。しかし,List 3では説明の都合上,直感的にわ
かりやすいレイアウトマネージャであるフローレイアウト(FlowLayout)を使っています。
コンテナfにFlowLayoutを設定している部分が,List 3-<3>の
  f.setLayout( new FlowLayout() );
という部分です。フローレイアウトマネージャの効果については,他のレイアウトマネー
ジャと一緒に後ほどまた説明します。

●ボタン
 さて,コンテナにレイアウトマネージャを設定したので,次は様々なコンポーネントを
追加していく過程を見ていきましょう。
 まずは,コンポーネントの代表選手であるボタン(button)です。ボタンを表すAWT版の
クラスはButtonです。List 3-<4>の
  Button b1 = new Button("Button1");
という部分でボタンオブジェクトb1を生成しています。コンストラクタの実引数文字列は,
ボタンに表示されるキャプションになります。
 こうして生成したボタンb1をコンテナに追加しているのが,List 3-<5>の
  f.add( b1 );
という部分です。前述しましたが,コンテナのadd()メソッドにより,コンポーネントをコ
ンテナに追加します
。同様に,List 3-<6>で2個目のボタンb2を生成・追加しています。
 そうして生成・追加された2このボタンが,Fig.4-(1)(a)に示された2個のボタンです。
各ボタンのキャプションがそれぞれ,"Button1","Button2"になっていますね。各ボタ
ンを押してみる(マウスでクリックする)と,ちゃんとボタンが反応しますので確かめてみ
てください。
 このボタンの例のように,コンポーネントは,生成して,add()メソッドで追加すれば
簡単に表示することができます。では,他のコンポーネントも追加していきましょう。

●ラベル
 ラベルは,文字列を表示するコンポーネントです(Fig.4-(1)(b))。ラベルの文字列内容は,
ユーザは変更できません。ラベルを表すAWT版のクラスは,Labelです。List 3-<7>の
  Label l1 = new Label( "Label1" );
がラベルを生成している部分です。コンストラクタの実引数文字列がラベルのキャプション
内容の初期値になります。生成したラベルオブジェクトl1を追加しているのが,List 3-<8>
です。List 3-<9>ではもうひとつラベルを生成・追加しています。

●チェックボックス
 チェックボックスは,チェックマークをつけることのできる矩形のコンポーネントです
(Fig.4-(1)(c))。チェックボックスを表すAWT版クラスはCheckboxです。
 List 3-<10>がチェックボックスを生成している部分です。コンストラクタの呼び出しは
  Checkbox( "Chack Box 1", true );
となっています。第1引数は,チェックボックスのキャプションです。第2引数は,このチェ
ックボックスがチェックされた状態(true)か,チェックされていない状態(false)かを指定し
ます。ここでは,チェックされた状態で生成していることになります。生成したチェックボ
ックスオブジェクトcb1をコンテナに追加しているのが,List 3-<11>です。
 同様に2個目のチェックボックスを生成しているのがList 3-<12>の部分です。この2個目
のチェックボックスcb2は,チェックされていない状態で生成されていることに注意してく
ださい。Fig.4-(1)(c)で1個目のチェックボックスはチェックされている状態,2個目のチェ
ックボックスはチェックされていない状態であることを確認してください。
 またFig.4の状態で,チェックボックスはすでにマウスクリックでチェックをつけたりはず
したりできるので試してみてください。また,両方のチェックボックスに同時にチェックを
つかられることも試してみてください。この,複数のチェックボックスに同時にチェックを
つけられる
ことが,次に紹介するラジオボタンとの大きな違いになっているのです。

●ラジオボタン
 ラジオボタンは,ON/OFFの状態を持つ丸いボタンです(Fig.4-(1)(d))。ラジオボタン
は複数個が一組(グループ)になって使用されます。そして,そのグループのうち,ONに
できるラジオボタンは1個だけ
です。つまり,ラジオボタンは,複数の選択肢の中から1個
だけを選ばせたいときに使用するコンポーネントです
。一方,チェックボックスは,複数
の選択肢の中から0個以上を選択させるときに使用するコンポーネント
,というわけです。
 実際に,Fig.4-(1)(d)の2個ラジオボタンを使ってみましょう。この2個のラジオボタン
はグループになっています。初期状態では,第1のラジオボタン(左側の方)がONになって
いて,第2のラジオボタン(右側の方)がOFFになっていますね。ここで,第2のラジオボタ
ンをクリックすると,第2のラジオボタンがONになって,第1のラジオボタンが自動的に
OFFになります。実際に確かめてみてください。さらに,第1のラジオボタンをONにしな
おすと,第2のラジオボタンが自動的にOFFになります。
 ラジオボタンを表すAWT版クラスは,チェックボックスと同じCheckboxです。では,
ラジオボタンを作成する方法を見てみましょう。
 ラジオボタンはその性質上,グループ化する必要があります。そのため,まずはラジオ
ボタンのグループを表すCheckboxGroup型オブジェクトを生成しておきます(List 3-<13>)。
そして,Checkbox型オブジェクトを生成するときに,コンストラクタでこのグループを
指定します。List 3-<14>では
  Checkbox("Radio Box 1",true, cbg);
というように,第3引数でグループを指定しています。このようにすると,このチェック
ボックスは,指定されたグループに所属することになります。そして,グループに所属し
たチェックボックスは,自動的にラジオボタンとなる
のです。作成したラジオボタンをコ
ンテナに追加している部分が,List 3-<15>です。同様に,同じグループに属する2個目
のラジオボタンをOFF状態で生成し,コンテナに追加しているのがList 3-<16>の部分で
す。こうして,生成・追加された2個のラジオボタンが,Fig.4-(1)(d)で表示されている
2個のラジオボタンというわけです。

●リスト
 リストは,複数の項目をスクロール可能な領域に並べて,ユーザに選択させるコンポー
ネントで,Fig.4-(1)(e)のような外観をしています。この状態でクリックによる項目選択
や項目のスクロールも可能ですので,確かめてみてください。リストは,多数の項目をで
きるだけ同時にユーザ見せて,そのうち1個(設定によっては2個以上)の項目を選択させた
いときに使います。
 リストを表すAWT版クラスは,Listです。List 3-<17>の
  List lst = new List( 3 );
がリストを生成しているところです。コンストラクタの引数は,同時に見せる項目数です。
この場合,3項目分を同時に見せられるようにリストコンポーネントの大きさが調整され
ます。ただし,スクロールバーがついている場合は,同時に見られる行数は,それより少
なくなることもあります。たとえば,Fig.4のリストコンポーネントでは,実際に見るこ
とのできる行数は2行になっています。また,行数を0とした場合,デフォルト値の4が使
われ,4行分を表示するように生成されることになります。
 リストの項目は,List 3-<18>のように,Listのadd()メソッドによって項目を追加する
ようになっています。リストをコンテナfに追加しているのが,List 3-<19>です。

●ポップアップメニュー
 ポップアップメニューは,複数の項目のうち1個だけをメニュー形式で選択させるコン
ポーネントです(Fig.4-(1)(f))。登録されている項目のうち,通常表示されているのは選
択されている項目だけで,クリックすることで選択可能な項目がメニュー形式で現れます。
Fig.4の状態で使用できますので,実際に項目を選択したりしてみてください。
 ポップアップメニューを表すAWT版クラスは,Choiceです。List 3-<20>がポップアッ
プメニューを生成している部分です。ポップアップメニューの項目は,Choiceのadd()メ
ソッドで登録します
(List 3-<21>)。作成したポップアップメニューをコンテナfに追加し
ている部分がList 3-<22>です。

●テキストエリア
 テキストエリアとは,テキストを複数行にわたって編集できるコンポーネントです(Fig.4-(1)(g))。
Fig.4の状態で,テキストエリア内のテキストを実際に編集できますので,試してみてくだ
さい。テキストの行数や桁数が多くなると,自動的にスクロールバーが現れますので,スク
ロールバーでテキストをスクロールさせてみてください。
 テキストエリアを表すAWT版クラスは,TextAreaです。List 3-<23>では,テキストエ
リアのテキスト内容の初期値strを用意しています。List 3-<24>でテキストエリアを生成し
ていますが,コンストラクタの第1引数は,テキスト内容の初期値,第2引数は表示行数,
第3引数は表示桁数となっています。生成したテキストエリアをコンテナfに追加しているの
がList 3-<25>の部分です。

●テキストフィールド
 テキストフィールドとは,1行だけのテキストを編集できるコンポーネントです(Fig.4-(1)(h))。
Fig.4の状態で,テキストを編集できますので,試してみてください。
 テキストフィールドを表すAWT版クラスは,TextFieldです。List 3-<26>では,テキス
トフィールドを生成しています。コンストラクタに渡した文字列は,テキスト内容の初期値
になります。List 3-<27>で,生成したテキストフィールドをコンテナfに追加しています。
 そして,List 3-<29>でコンテナfを可視状態にすることで,Fig.4のように各種コンポー
ネントを含んだウィンドウが表示されるというわけです。

【レイアウトの方法】
 さて,ここでフローレイアウトの効果についてお話しし,他のレイアウトマネージャの
例としてグリッドレイアウトを紹介することにします。また,コンテナの大きさを自動調
整してくれるpack()メソッドについて説明します。そして,コンポーネントの配置に非常
に有用な特殊なコンテナ,Panelについても紹介することにしましょう。

●フローレイアウト
 フローレイアウトのフロー(flow)とは,“流れ”という意味です。文字通り,フローレ
イアウトマネージャは,コンテナの中に,コンポーネントを“流し込む”ように配置しま
す。具体的には,add()メソッドで追加した順番で,コンポーネントをコンテナ内の上から
下へ配置していきます。コンテナの幅に余裕がある場合には,同じ行に複数のコンポーネン
トを配置し,残りのコンポーネントは,その下の行以降へ同様に配置されていきます。行内
のコンポーネントは,(デフォルトでは)中央にそろえられます。
 Fig.4を見ると,List 3でadd()メソッドを使って追加された順番で,各コンポーネントが
ウィンドウの上から下に詰められていることがわかります。
 レイアウトマネージャは,基本的にコンテナの大きさが変更された場合,コンポーネント
を再配置します。フローレイアウトを例にその様子を見てみましょう。List 3を実行して,
Fig.4のようにウィンドウを表示させてください。そして,マウスでウィンドウのサイズを
変えてみてください。
 実際にウィンドウのサイズをいろいろ変えた例を,Fig.5-(1)〜(3)に示します。ウィンド
ウ(コンテナ)の大きさに合わせて,コンポーネントの再配置が実行されていることがわかり
ますね。Fig.5-(1)では,同じ行内のコンポーネントが左詰めでもなく右詰めでもなく,中央
揃えに配置されている様子がよくわかります。
 なお,ウィンドウの横幅は,各コンポーネントが十分表示できるまではせばめられますが
(Fig.5-(3)),それ以上はせばめられなくなります。


●グリッドレイアウト
 フローレイアウトは,プログラマが実際の配置にほとんど気を遣わなくていい分,便利
なのですが,それが逆に困った状態をひきおこすことがあります。たとえば,Fig.5-(1)で
は,2個あるチェックボックスが2行に分かれてしまってます。これでは,ユーザはこのソ
フトを使いにくいと思うことでしょう。
 そういった場合,他のレイアウトマネージャを使えばいいわけです。ここでは,ある程度
コンポーネントの配置を予測できるレイアウトマネージャの例として,グリッドレイアウト
を紹介しましょう。
 グリッドとは,“格子”のことです。グリッドレイアウトマネージャ(クラスはGridLayout)
は,コンポーネントを格子状に配置するレイアウトマネージャです。実際にグリッドレイアウ
トを使用した例が,List 4です。
List 4 GridTest.java

List 4-<①>でjava.awtパッケージをインポート,List 4-<2>,<3>で200pixel四方のウィ
ンドウを生成しています。そして,グリッドレイアウトマネージャをコンテナ(ウィンドウ)f
に設定している部分が,List 4-<4>です。GridLayoutのコンストラクタ呼び出しは
  GridLayout( 3, 2 )
となっていますが,これは3行2列の格子を作成することになります。List 4-<5>で5個のボ
タンを生成・追加し,List 4-<7>でウィンドウを表示しています。
 List 4の実行結果がFig.6です。3行2列の格子状にボタンが配置されていることがわかります。
デフォルトの状態では,追加された順番に,格子の左上を起点として,左から右,上から下へ
向かってコンポーネントが配置されます。ウィンドウの大きさにあわせて,ボタンの大きさが
調整されていることに注意してください。



●ウィンドウのパック
 ところで,List 3-<2>やList 4-<3>では,setSize()メソッドを使ってウィンドウの大
きさを設定していました。しかし,前述したように,プラットフォームによってコンポー
ネントの外形が異なるなら,このようにあらかじめウィンドウの大きさを決めてしまうの
は,危険であるということになります。追加したコンポーネントが,ウィンドウの領域の
中に入りきらない可能性があるからです。
 そこで,登録されているコンポーネントの情報から,自動的にウィンドウの大きさを適
切なサイズに調整するメソッドpack()が役に立ちます。
 List 3-<28>とList 4-<6>では,
  f.pack();
というpack()の呼び出し部分がコメントアウトされていますが,これを有効にしてList 3,
List 4を実行してみてください。修正したList 3とList 4の実行結果は,それぞれFig.7-(1),
Fig.7-(2)のようになります。


 フローレイアウトの場合(Fig.7-(1))は,pack()メソッドが呼ばれると,すべてのコンポ
ーネントが1行に収まるようにウィンドウの大きさが自動調整されます。ウィンドウの大き
さを変えようとしてマウスで操作しても,横幅と高さはこれ以上せばめられません。
 また,グリッドレイアウトの場合(Fig.7-(2))は,pack()メソッドが呼ばれると,指定さ
れた格子を保ったまま,ボタンが標準の大きさ・形になり,すべてのコンポーネントが収ま
るようにウィンドウの大きさが調整されます。ウィンドウの大きさを変えようとしてマウス
で操作しても,横幅と高さはこれ以上せばめられません。
 以上のように,ウィンドウをパックすることで,ウィンドウの大きさを気にすることなく,
コンポーネントを追加することが可能になります。ですので,
  (1)コンテナにレイアウトマネージャを設定する
  (2)コンテナにコンポーネントを追加する
  (3)最後にウィンドウをパックする
という手順は,ひとつの定石ですのでおぼえておいてください。

コラム【パネルによる高度なレイアウト】
 パネルという特別なコンテナを使うと,より複雑なレイアウトを行うことができます。パネルは,他のパネルを含むことができます。当然,個々のパネルには異なったレイアウトマネージャを設定できます。したがって,パネルを入れ子で配置することで,階層的に複雑なコンポーネント配置が実現できるのです。
 パネルを表すAWT版クラスは,Panelです。実際にパネルを使って,下図のようにコンポーネントを配置してみましょう。



手順は次のようになります。まず,2行2列のグリッドレイアウトを持つパネル1にボタンを4個配置します(上図-(1)(a))。そして,フローレイアウトを持つパネル2に,テキストエリアとボタンを配置します(上図-(b))。次に,1行2列のグリッドレイアウトを持つパネル3に,パネル1とパネル2を追加します(上図-(1)(c))。そして,パネル3をウィンドウ(上図-(1)(d))に追加します。
 実際のプログラムが,下のソースプログラムです。
List AWTPanel.java


List-<①>でjava.awtパッケージをインポート,List -<2>でFrame型ウィンドウを生成します。List -<3>でパネル1を生成し,List-<4>で2行2列のグリッドレイアウトをパネル1に設定します。List-<5>で,ボタンを4個,パネル1に追加します。
 List-<6>ではパネル2を生成し,List-<7>ではパネル2にフローレイアウトを設定します。List-<8>で,パネル2にテキストエリアとボタンを追加します。
 List-<9>では,パネル3を生成し,List-<10>では,このパネル3に1行2列のグリッドレイアウトを設定しています。そして,ここが重要ですが,List-<11>で,パネル3にパネル1とパネル2を追加しています。最後に,パネル3をウィンドウfに追加し(List-<12>),ウィンドウfをパックして(List-<13>),ウィンドウfを可視化します(List-<14>)。
 このソースプログラムの実行結果が上図の(2)です。上図の(1)の設計どうりにコンポーネントが配置されていることを確認してください。



【Swingの場合】
 これまでは,AWTのコンポーネントを中心に見てきました。次にSwingの場合を見てみ
ましょう。Swingの場合も,AWTとほとんどかわらないのですが,ひとつ注意しなければ
ならないことがあります。

【Swingのペイン】
 Swingでは,ペイン(pane)という考え方が取り入られています。paneとは,“(長方形
状の)区画”というような意味です。Swingでは,GUI上の特定の長方形領域に,特定の機
能を持たせるために,このペインを使用します。
 そして,Swingのウィンドウ(JFrame,JWindow,JDialog)には,コンテントペイン
いう特殊なペインが1個だけ存在します。英語でcontentとは,“中身”という意味です。
つまり,コンテントペインとは,ウィンドウの“中身の区画”というような意味です。
そして,Swingではこのコンテントペインに対してレイアウトマネージャを設定したり,
コンポーネントを追加したりしなければならない
のです。
 ウィンドウの持つコンテントペインを得るには,ウインドウの
  getContentPane()メソッド
を使います(このメソッドは,コンテントペインをContainer型として返す)。つまり,ウィ
ンドウをfとしたとき,AWTではfにコンポーネントcを追加するには
  f.add( c );
としましたが,Swingでは同じことを
  f.getContentPane().add( c )
としなくてはならないわけです。

【Swingのコンポーネント】
 Swingの代表的なコンポーネントとしては,
  ・ボタンを表すJButton
  
・ラベルを表すJLabel
  ・チェックボックスを表すJCheckBox
  ・ラジオボタンを表すJRadioButton
  ・リストを表すJList
  ・ポップアップメニューを表すComboBox
  ・テキストエリアを表すJTextArea
  ・テキストフィールドを表すJTextField
などがあります。
 AWTのコンポーネントのSwing版には,AWTでの名称に頭文字Jをつけたものが用意さ
れている
ことがわかりますね。ただし,ポップアップメニューは,AWTではChoiceでした
が,SwingではJComboBoxという名称になっています。ちょっとややこしいのですが,
SwingにはJPopupMenuというコンポーネントもあり,これはマウスの右クリックで出現
するメニューのことを意味します。
 そのほか,AWTのチェックボックスは,Chekboxでしたが,Swingのチェックボックス
は頭ににJがつくだけでなく,bが大文字になってJCheckBoxとなっています。
 そして,AWTではラジオボタンはチェックボックスの一種として用意されていましたが,
Swingではチェックボックスを表すJCheckBoxとラジオボタンを表すJRadioButtonは,独
立したクラスになっています。
 なお,リストやテキストボックスなどのように,スクロールをともなうSwingコンポー
ネントは,スクロールをサポートするための特別なペインJScrollPaneと連携させること
で,スクロール可能になります。
 もちろんSwingには,AWTには無かった新しいコンポーネントも用意されていますが,
ここでは割愛させていただきます。
 では,List 3をSwingを使って書き換えたリストをList 5に示します。主にList 3との違い
を説明してきましょう。まず,List 5-<①>ではjava.awtとjavax.swingをインポートしてい
ます。Lsit 5-<2>では,JFrame型ウィンドウfを生成しています。
 前述の通り,Swingではレイアウトマネージャやコンポーネントを登録するためには,
コンテントペンを取得しなければなりません。List 5-<3>では,fのコンテントペインを
取得して,Container型変数cntpaneに代入しています。List 5-<4>で,コンテントペイ
ンにフローレイアウトを設定しています。
List 5 SwingComponents.java

●JButtonとJLabel
 List 5-<5>ではSwing版のボタンJButton型オブジェクトを生成して,List 5-<6>でコ
ンテントペインに追加しています。List 5-<7>ではもう1個ボタンを生成・追加していま
す。List 5-<8>,<9>では,Swing版ラベルJLabel型のオブジェクトを生成し,コンテン
トペインに追加しています。List 5-<10>ではもう1個のラベルを登録しています。

●JCheckBoxとJRadioButton
 List 5-<11>,<12>では,Swing版チェックボックスのJCheckBox型オブジェクトを生
成し,コンテントペインに追加しています。List 5-<13>ではもう1個,チェックボックス
を生成・追加しています。
 List 5-<14>では,Swing版のラジオボタンJRadioButtonを生成しています。Swing版
のラジオボタンは,AWTと違い,グループ化しなくても単独で生成できます。List 5-<15>
で,生成したラジオボタンをコンテントペインに追加しています。List 5-<16>ではもう
1個ラジオボタンを生成・追加しています。

●JListとJScrollPane
 List 5-<17>〜<21>では,Swing版のリストJListを生成・追加しています。AWTのList
とちが違い,リスト項目を追加するadd()メソッドはJListにはありません。JListに項目を
追加する方法はいくつかありますが,ここでは文字列配列をコンストラクタに渡す方法を使
いましょう。
 List 5-<17>でリスト項目を格納する文字列配列citiesを定義しています。そして,この
文字列配列citiesをJListのコンストラクタに渡してJListを生成します。
 表示しておく項目数は。List 5-<19>のように,setVisibleRowCount()メソッドを使い
ます。
 リストなどのコンポーネントでスクロールを行う必要がある場合は,前述のようにJScrollPane
という特殊なペインを使います。使い方は簡単で,スクロールが必要なコンポーネントを,
JScrollPaneのコンストラクタに渡してJScrollPane型オブジェクトを生成します
(List 5-<20>)。
そして,生成したJScrollPane型オブジェクトの方をコンテナに追加するようにするのです
(List 5-<21>)。

●JComboBox
 List 5-<22>では,Swing版のポップアップメニューであるJComboBox型オブジェクトを
生成しています。AWTのChoiceと異なり,メニュー項目を追加するadd()メソッドはありま
せん。メニュー項目を追加するひとつの方法は,List 5-<22>で行っているように,文字列
配列をコンストラクタに渡す,というものです。List 5-<23>で,生成したポップアップメ
ニューをコンテントペインに追加しています。

●JTextAreaとJScrollPane
 List 5-<24>〜<26>は,Swing版のテキストエリアJTextAreaを生成・追加しています。
テキストエリアも,スクロール機能が必要になる場合は,List 5-<25>のように,JTextArea
型オブジェクトを,JScrollPaneのコンストラクタに渡して,JScrollPane型オブジェクトを生
成し(List 5-<25>),そのJScrollPane型オブジェクトをコンテナに追加するようにします(List 5-<26>)。

●JTextField
 List 5-<27>は,Swing版テキストフィールドJTextFieldを生成している部分です。List 5-<28>
で生成したテキストフィールドをコンテントペインに追加しています。

【次回は】
 今回は,いろいろな種類のコンポーネントを紹介し,実際に配置させてみるだけでしがた。
しかし,それだけでは意味がありいません。コンポーネントが操作されたとき(たとえばボタン
を押したとき)に,アプリケーションを反応させなくてはなりません。そのために,“イベント
処理”というメカニズムを使わなくてはなりません。次回は,PanelのSwing版であるJPanelを
紹介した後,イベント処理について解説する予定です。


戻る