画面のちらちきを減らすには、オフスクリーンバッファを使います。昔のパソコンのゲーム作成の解説書などに書かれていた仮想画面と同じ物だと思います。画面に直接描いていくとその過程が見えてしまうので、まずオフスクリーンバッファに全て描いてから、その内容をいっきに表示します。オフスクリーンバッファはjava.awt.ComponentのcreateImageメソッド(ダブルバッファリングのために使用されるオフスクリーン描画イメージを作成する)を使います。
Image offs = new createImage(200, 200);このようにすると幅200、高さ200のオフスクリーンバッファが作られます。実際には、オフスクリーンバッファが他のメソッドからもアクセスできるようにoffsをインスタンス変数にします。Imageのインスタンスのoffsには直接描画できないので、Graphicsインスタンスを作ります。java.awt.ComponentのgetGraphicsメソッド(コンポーネントのGraphicsコンテキストを得る)でオフスクリーンバッファのGraphicsインスタンスを得ます。 ついでに固定だった画面サイズを汎用にします。幅と高さを実際の表示領域から得るためにjava.awt.ComponentのgetSizeメソッド(このコンポーネントの現在のサイズを返す)を使います。これをinitメソッドで行ないます。JDK1.0.2でのサンプルではjava.awt.Componentのsizeメソッドをこの目的で使っていますが、JDK1.0.xではコンパイル時に警告が出るのでgetSizeに変更します。 Dimension d; // 表示領域 Image offs; // オフスクリーン Graphics grf; // オフスクリーンのGraphicsインスタンス public void init() { // 初期化 d = getSize(); offs = createImage(d.width, d.height); grf = offs.getGraphics(); }initでオフスクリーンバッファが用意できたのでpaintメソッドを変更します。Graphicsインスタンスgに直接描画せずにオフスクリーンバッファのGraphicsインスタンスgrfに描くように変更します。色のセットg.setColor(newColor);をgrf.setColor(newColor);に変更します。その色で画面を塗りつぶすg.fillRect(0, 0, 200, 200);も同様に変更し、サイズを汎用にするため、200,200をd.width, d.heightにします。そして、オフスクリーンバッファの内容を実際の画面に表示するためにjava.awt.Graphicsクラスの drawImageメソッドを使います。paintは次の様になります。 public void paint(Graphics g) { grf.setColor(newColor); // 色のセット grf.fillRect(0, 0, d.width, d.height); // 画面を塗る g.drawImage(offs, 0, 0, this); // 実際の画面に表示 }これで変更は完了です。プログラム全体とアプレットを示します。 Test205アプレット表示 ソース・ダウンロードTest205.java |
残念ながら変わりないようです。オフスクリーンバッファは見えないところで画面を書き換えてちらつきを抑えるので画面全体の色を変える今回のプログラムには効果はなかったようです。では、何故ちらつくのかを考えてみましょう。画面の描画にまずpaintが呼ばれます。その後、スレッドが開始してrunの中からrepaintが呼ばれます。repaintはupdate読んで、updateがpaintを読んでいました。repaint、updateが実際に何をしているかjava.awt.Componentのソースを見て確認します。 repaintがupdateを呼び出すところは確認できませんでしたが、updateがpaintを呼び出しているところを確認できました。背景色をセットして画面全体に塗ってからpaintを呼び出していてるようです。背景色で画面を塗るのは画面をクリアしている事になります。(このクリアは条件文になっているので必ずクリアされる訳ではありません) 今のプログラムでは背景色をセットしていませんが、背景色にも変化していく色をセットすればちらつきを減らせそうです。背景色のセットはjava.awt.ComponentのsetBackgroundメソッドを使って次の様にします。 setBackground(newColor);paintで画面を塗り替えるたびに、背景色にその色をセットしておけばクリアしてもちらつきません。paintメソッドはこの様になります。オフスクリーンバッファをやめています。プログラムとアプレットを示します。 public void paint(Graphics g) { g.setColor(newColor); // 色のセット g.fillRect(0, 0, d.width, d.height); // 画面を塗る setBackground(newColor); // 背景色のセットjava.awt.Component } Test208アプレット表示 ソース・ダウンロードTest208.java |
ちらつかなくなりましたね。今回は画面全体に色を付ける以外なにも表示して無いのでこれで解決しましたが、何か表示しようとした場合には背景色に何をセットしていても背景色と違う色の部分は一瞬消えてしまうのでちらついて見える可能性があります。画面に色々な色がある場合にちらつかないようにするにはどうしたら良いのでしょうか。 そもそもupdateメソッドでの画面のクリアが問題なのですから画面のクリアを止めてしまったらどうでしょう、または表示画面をクリアするのでなく、オフスクリーンを使ってオフスクリーンの方をクリアする様にしたらどうでしょうか。オフスクリーンのクリアは必要なら考えるとして、クリアを止めてみましょう。updateメソッドをオーバーライドして画面をクリアせずにpaintを呼び出す様に変更します。 public void update(Graphics g) { // オリジナル update() は画面クリアでちらつくので // クリアなし paint(g); } Test206アプレット表示 ソース・ダウンロードTest206.java この方法は解説書などでもちらつきを無くす方法としてオフスクリーンバッファの方法と共に出ています。 ここで気になるのは画面クリアに付いていた条件文です。確かに解説書の例では気にしないでオーバーライドしていますが、多くの解説書はJDK1.0.2によるものです。JDK1.1.xで変更された可能性の高いこの部分を気軽に無視できません。良く見るとLightweightコンポーネントをサポートするための追加のコードが書かれているようです。Lightweightコンポーネントを使わない限り余り気にしなくて大丈夫そうです。 これから先、このプログラムを元にグルグルを作っていくのににオフスクリーンバッファで描画過程を隠すのは有効な方法なので、updateのオーバーライドと両方を合わせたプログラムを載せて終わりにします。 ソース・ダウンロードTest207.java これまでの説明の中で作ってきたTest207.javaと、はじめに示したTest041sとは少し違っています。Javaを十分に理解していないので、前のプログラムの書き方に不満な部分がでたり、説明する必要の無いと思われる部分などが次々出てきてしまいます。その部分を変更したり省いたりしました。 |