Previous | Next | Trail Map | Creating a User Interface | Java UI の概説


描画

GUI を備えた Java プログラムがそれ自身を描画する必要がある場合、それが最初の 描画か、隠れていない状態に戻されたためか、プログラム内で発生した何かを反映さ せるために外観を変える必要が生じたのかにかかわらず、再描画する必要がある構成 要素の最も高い階層から (たとえば、階層の頂点の コンポーネント から) 始めて、最 下部の コンポーネント へ向かって描画していく。 これはすべて AWT 描画システムによって調整される。

Converter アプリケーションがそれ自身を描画するとき、以下のことが発生する。

  1. Frame がそれ自身を描画する。
  2. Converter オブジェクトがその領域の周りにボックスを描いて、それ自身を描 画する。
  3. 2 つの ConversionPanel の 1 つは、その領域の周りにボックスを描いて、そ れ自身を描画する。
    注: 同じレベルにある 2 つの コンポーネント が描画される順序は定まっていない。たとえば 、metric パネルが U.S. パネルより先に描かれるかどうかはわからない。 同様に、2 つの コンポーネント が異なる レベルにあって、低い方の コンポーネント が高い方の コンポーネント に含まれていない場合も、その 2 つの コンポーネント の描かれる順番は定まっていない。
  4. ConversionPanel のコンテンツ、すなわち Label、TextField、Scrollbar、 Choice がそれら自身を描画する。


このように、それぞれの コンポーネント は、内部に含んでいる コンポーネント より前に自分自身を描画する。 このことから、たとえば Panel のバックグラウンドは、それが含んでいる コンポーネント によって隠されていない場所だけで可視となるわけである。

描画要求が発生する仕組み

プログラムが描画できるのは、AWT に指示されたときだけである。 この理由は、コンポーネント がそれ自身を描くということは常に、割り込みのない状態で 実行されなければならないからである。そうでなければ、ボタンの描画途中で、時間の かかる動画に割り込まれるなど、予測できない結果が生じる可能性が出てくる。 AWT は、描画要求をシングルスレッドで実行することにより描画の順序を設定してい るが、コンポーネント では repaint() メソッドによって描画のスケジュー ルに組み入れるよう要求することができる。

AWT は、コンポーネント の update() メソッドを呼び出して、コンポーネント にそれ自身を描画するよう要求する。update() メソッドのデフォルトの (コンポーネント の) 実装は、コンポーネント のバックグラウンドをクリアし (そのコンポーネントのクリップ領域の 上に コンポーネント のバックグラウンドカラーで矩形を描画する)、その コンポーネント のpaint() メソッドを呼び出すだけである。paint() メ ソッドのデフォルトの実装は何も行わない。

Graphics オブジェクト

paint() および update() メソッドへのただ 1 つの引 数は、コンポーネント がその描画を実行できるコンテキストを表すGraphics オブジェクトである。 Graphics クラスは次のことを行うメソッドを提供する。

描画の仕組み

コンポーネント がそれ自身を描く最も単純な方法は、その paint() メソッ ドに描画を行うコードを入れることである。 これは、AWT が描画要求を出すとき (コンポーネント の update() メ ソッドを呼び出す。このメソッドは 上記 のように 実装されている) に、コンポーネント 全体の領域がクリアされ、その コンポーネント のpaint() メソッドが呼び出されるということである。それ自身をあま り頻繁にはリペイントしないプログラムの場合は、この方式で性能も良好である。

重要:paint()update() メソッドは高速に実行されなければならない! そうしないと、プログラムの目で見える性能が大きく損なわれる。 ペイント要求の結果として何か時間のかかる操作を実行する必要がある場合は、別の スレッドを始動して (または何らかの方法で別のスレッドへ要求を送信して) その操 作を実行すべきである。 スレッドの使用法については、スレッド のコントロール(in the
Writing Java Programs trail)を参照する。

以下に paint() メソッドの実装例を示す。 Converter と ConversionPanel クラスはどちらもこのコードを使って領域の周りに ボックスを描いている。 (どちらのクラスも、パネルのコンテンツの周りのパディングを指定する、insets() メソッドも実装している。このメソッドがなければ、paint() メソッ ドによって描かれたボックスが、パネルのコンテンツの外部境界にオーバラップする ことになる。)

public void paint(Graphics g) {
    Dimension d = size();
    g.drawRect(0,0, d.width - 1, d.height - 1);
}

それ自身を頻繁にリペイントするプログラムの性能を上げるには、2 つのテクニック がある。1 つは update()paint() を両方とも実装 すること、もう 1 つはダブルバッファリングを利用することである。このようなテ クニックについては [まだない] で説明する。


Previous | Next | Trail Map | Creating a User Interface | Java UI の概説