グラフィックスを扱う |
前のページでは、update() メソッドを実装することによってフラッシ ングを排除する方法を示した。 ただし、結果のアプレットではフラッシングはなくなったが、(使用中のコンピュー タのパフォーマンスによっては) ゆっくりと這うように見える可能性がある。つまり 、描画領域 (またはフレーム) 全体がただちに更新されるのではなく、 ある一部が、そのすぐ右にある部分より先に更新されることがあるため、列の間で描画が均等に行われていないことが見えてしまうのである。
フレーム全体を同時に描画させ、這うような動きを避けるには、ダブルバッファリン グを使用するとよい。ダブルバッファリングを実装するときは、画面には表示されな いバッファ (バックバッファ やオフスクリーンバッファ とも呼 ばれる) を作成し、それに描画した後で、結果のイメージを画面上に表示するように する。
ダブルバッファリングを実装するように変更されたグラフィックスの動画例のコードも参照できる。 以下に、結果のアプレットが動作する様子を示す。
使用中のブラウザは 1.0 Java アプレットを実行することができない。したがってここでは実行中のスナップショットを示す。
AWT を使用してオフスクリーンバッファを作成するには、まず、適切なサイズのイメ ージを作成し、そこにそのイメージを操作するためのグラフィックスコンテキストを 取り込む必要がある。 以下に示すのは、これを行うコード部分である。
//インスタンス変数を宣言する。 Dimension offDimension; Image offImage; Graphics offGraphics; . . . //update() メソッドにおいて、d が画面上の描画領域の //サイズを保持する。 if ( (offGraphics == null) || (d.width != offDimension.width) || (d.height != offDimension.height) ) { offDimension = d; offImage = createImage(d.width, d.height); offGraphics = offImage.getGraphics(); }以下にボールド書体で示すのは、update() メソッドの新規の 描画コードである。 この描画コードは背景全体をクリアするが、フラッシングを引き起こさないことに注 意する。 これは、コードが画面ではなく、オフスクリーンバッファに描いているからである。 また、fillRect() へのすべての呼び出しもオフスクリーンバッファに 対して実行される。最終的な結果は、update() メソッドが戻る直前に 画面に描画される。
public void update(Graphics g) { ...//上に示したように、まず、変数を初期化し、 //オフスクリーンバッファを作成する。その後で、前の //イメージを消去する: offGraphics.setColor(getBackground()); offGraphics.fillRect(0, 0, d.width, d.height); offGraphics.setColor(Color.black); ...//矩形を描画するまでは、前の paint() メソッドと //同じことを行う。 if (fillSquare) { offGraphics.fillRect(x, y, w, h); fillSquare = false; } else { fillSquare = true; } ...//残りの部分のうち、末尾に次のコードを追加するところまでは、 //前の paint() メソッドとまったく同じである。 //イメージを画面上にペイントする。 g.drawImage(offImage, 0, 0, this); }update() メソッドから paint() メソッドを呼び出す必 要はない。 必要なのは、 update() メソッドが何らかの方法でそのオフスクリーンバッファを画 面に描画することと、 paint() メソッドが AWT から直接呼び出されたときに適切なイメージ を描画できるようにしておくことである。
オフスクリーンイメージやグラフィックスコンテキストが、(たとえば) start() メソッドではなく、update() メソッドで作成 されることを不思議に思われるかもしれない。 この理由は、イメージとクラフィックスコンテキストは、アプレットの Panel の描 画領域のサイズに依存し、Component の描画領域のサイズはどれも、Component が初めて画面に描画されるときまで有効ではないからである。
グラフィックスを扱う |