== ウインドウの内容 == 窓は窓枠と窓ガラスでできています。 . {{attachment:swing04.png}} 窓枠に対応するのがJFrameです。 窓ガラスがはまる部分に処理内容に対応した部品を配置し、配置したインスタンスを通して処理を行います。 部品にはボタンやメニューなどもあります。 ---- === 部品の配置 === このプログラムでは基本的な部品であるJPanelを配置しています。 {{{#!java import javax.swing.*; import java.awt.*; public class Sample3 { public static void main(String[] args) { JFrame f; Container cp; JPanel p; f = new JFrame(); f.setVisible(true); f.setTitle("swing"); f.setSize(200, 300); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cp = f.getContentPane(); p = new JPanel(); cp.add(p); } } }}} JFrame, Container, JPanelの3つのクラスを利用しています。 . JFrame, JPanelは javax.swingパッケージに含まれます。 . Containerはjava.awtパッケージに含まれます。 . これらを利用するためimport文が2行あります。 12~16行目はウインドウ枠の処理です。[[ウインドウの表示]]を参照。 枠の内側で部品を配置できる場所を!ContentPaneと呼び、クラスはContainerです。 . 18行目 cp = f.getContentPane(); . JFrameインスタンスfの!ContentPaneを得て、変数cpに記憶しておきます。 . 19行目 p = new JPanel(); . 配置したいJPanelインスタンスを作成します。 . 20行目 cp.add(p); . cpにaddメソッドを用いて部品pを配置します。 この結果インスタンスの状態はこのようになります。 . {{attachment:swing05.png}} '''注''' . java1.5以降ではcpを使わずにf.add(p)と書けるようですが、JFrameにJPanelがaddされるわけではなく、上と同様の処理が行われます。 {{{#!java public static void main(String[] args) { JFrame f; JPanel p; f = new JFrame(); f.setVisible(true); f.setTitle("swing"); f.setSize(200, 300); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); p = new JPanel(); f.add(p); } }}} ---- === 描画 === GUIではプログラムの実行開始時にだけ、ウインドウ内部が描画されるわけではありません。 ウインドウの大きさが変えられたり、ボタンが押されたり、文字が入力されたり など、いろいろな場面で描画が行われます。 . JPanel上の'''描画が必要になったとき'''には、JPanelクラスの'''paintComponent'''メソッドが実行されます。 JPanelクラスのpaintComponentメソッドではプログラムで表示内容を指定できません。 . JPanelクラスを継承して'''サブクラスを作成'''し、paintComponentメソッドを記述します。 . {{attachment:swing06.png}} サブクラス名を Sample4 とした例を示します。 {{{#!java import javax.swing.*; import java.awt.*; public class Sample4 extends JPanel { public void paintComponent(Graphics g) { g.drawRect(50,50,100,150); } } }}} paintComponentは引数としてGraphicsクラスのインスタンスをとります。 この例では変数名をgとしています。 描画はインスタンスgに対してメソッドを使って指示します。 drawRectは長方形を描くメソッドです。 引数は左上のx座標,y座標,横幅,縦幅です。 座標系は図のとおりです。 . {{attachment:zahyo.png}} ---- 上のサンプルプログラムSample3でJPanelとなっていた箇所を、 このクラス(Sample4)で置き換えます。 {{{ public static void main(String[] args) { ... JPanel p; ... p = new Sample4(); ... } }}} するとContainerに配置されるのはSample4クラスのインスタンスとなり、 描画が必要なときにはSample4クラスのpaintComponentが実行されます。 変数pの宣言は JPanel p; のままになっていますが、代入されるインスタンスはSample4クラスのものです。 * 理由は継承のところで説明しました。 * 変数宣言を Sample4 p; としてもかまいません。 ---- === mainメソッドをどこに記述するか === mainメソッドは特殊なメソッドで、どのクラス内に記述するかはあまり意味を持ちません。 コマンド >java クラス名 を行うと、そのクラス内のmainメソッドが実行されるだけです。 クラスの機能は普通のメソッドとして記述し、 mainメソッドは主として動作確認のために使ってきました。 '''例1''' 上のサンプルではSample4.javaでクラスを定義し、 Sample3.javaにSample4クラスを利用するmainメソッドを記述しています。 この場合、コンパイル後 . > java Sample3 で実行できます。 コンパイルは2つのファイルを別々に行っても良いし、 mainメソッドのあるSample3.javaをコンパイルすれば一緒にコンパイルされます。 '''例2''' ウインドウを作成し表示するためのmainメソッドを、 Sample4クラス内に記述すれば Sample4.javaだけを作成、コンパイルし . > java Sample4 で実行できます。(プログラムは1つのファイルで済みます) {{{ public class Sample4 extends JPanel { void paintComponent(...) { ... } public static void main(...) { ... } } }}}