- ベストアンサー
アプリケーション内でのダブルバッファリング
ダブルバッファを用いてアニメーションを表示するアプリケーションを作成しているのですが、 createImageメソッドを呼び出すタイミングに困っています。 これがアプレットならinitで呼び出すところなのですが、 アプリケーションのmainはstaticなのでcreateImageは置けません。 ならばとコンストラクタで呼び出したところ、NullPointerExceptionが返ってきました。 応急措置としてpaintメソッドの冒頭で呼び出していますが、 createImageをスレッドの実行中わざわざ毎回呼び出すのは、如何にも非効率な気がします。 もっとうまい方法がありましたら、何方か御教示ください。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
JavaでcreateImage他いくつかのグラフィック関連メソッドがコンストラクタ内で正常に機能しないのは、グラフィック関連の機能をネイティブスクリーンリソースに委譲しているからです。このネイティブなリソースとの受け渡しはピア(Peer)と呼ばれるオブジェクトが管理しており、これはコンストラクタの処理終了後、addNotify内で生成されます。 整理すると、コンポーネント類の生成からグラフィック関連機能が使えるようになるまでの経緯は、 コンストラクタ実行 ↓ addNotify実行 →pearの生成 ※これよりネイティブリソース利用可能 addNotify終了 ↓ 他のメソッドの処理へ続く こういう感じになります。 そこで、私の場合はcreateImageなどの処理はaddNotifyをオーバーライドし、その中で行うようにしています。 public void addNotify(){ super. addNotify(); img = createImage(・・・); } こんな感じのメソッドをおくわけですね。スーパークラスでaddNotifyが処理されて以降はcreateImageは問題なく動作しますので、これがタイミングとしてはもっともよいかと。 また、暫定的な感じですが、よく使われる方法としてはpaint内でifを使ってnullチェックを行い1度だけcreateImageを呼び出すというものです。 public void paint(Grahics g){ if (image == null){ image = createImage(・・・); } ・・・略・・・ } こういう感じですね。オフスクリーンのイメージが必要になるのは何かを画面に描画する際ですから、もっとも遅いタイミングとしては、「再描画の直前に用意されていればいい」わけです。 ただ、再描画の度に余計なifをチェックするのが気持ち悪いという人はいるかも知れません。
その他の回答 (2)
- PecoPlus
- ベストアンサー率76% (144/188)
#1です。 ちなみにSwingを使って作成している場合は、ダブルバッファリングの必要性はないですよ。 SwingのJFrameやJAppletが標準でダブルバッファリングをサポートしているので、普通にコンポーネントのpaintメソッドでゴリゴリ描いて、JFrameやJAppletのrepaintメソッドを呼べばいいです。
お礼
重ね重ね、ありがとうございます。 私はこれまでAWTしか使ってこなかったので、 Swingが標準でダブルバッファをサポートしていることは知りませんでした。 これを機に、いろいろ調べて使ってみようと思います。 どうもありがとうございました。
- PecoPlus
- ベストアンサー率76% (144/188)
こんにちは。 JFrameなどのコンストラクタでcreateImageメソッドを呼んでもnullしか返ってこないは、まだ、スクリーンリソースが作られていないからです。 スクリーンリソースは、はじめてフレームのshowメソッドが呼ばれたり、packメソッドが呼ばれたりしたタイミングで作られるので、createImageメソッドを呼ぶタイミングが早すぎるのです。 フレームのwindowOpenedイベントで作るのがタイミング的には一番いいのではないでしょうか。
お礼
御回答ありがとうございます。 考えてみれば確かに、コンストラクタの段階ではイベントは何も発生していないんですよね。 windowOpenedの存在には気がつきませんでした。 どうもありがとうございました。勉強になりました。
お礼
御回答ありがとうございます。 御教示いただいた方法でうまく行きました。 実は私もスーパークラスのオーバーライドとして show() { super.show(); buffer = createImage(・・・); } を試してみたのですが、 コンパイラに文句を言われた上に問題が解決しなかったため、 この方法は諦めていました。 また、ネイティブリソースに関する御教示は参考になりました。 今後、JVMそのものについても勉強してみようと思います。 本当にありがとうございました。