2

今日、私はこのトピックについて、単純な 2D ゲームで Java2D API を「誤用」するというさまざまなアイデアに取り組んでいる多くの仲間の学生と議論してきました。

メソッドを拡張JComponentおよびオーバーライドしてオブジェクトを取得し、そこからレンダリング ロジックを定義するクラスを使用しています。変更されたのは私のオーバーレイです。paintComponent()Graphics2DJComponentcontentPaneJFrame

ここに私の質問があります:とのバックエンドでの呼び出しpaint(Graphics)は、私の画面にどのような違いをもたらしますか? 「フレーム タイマー」以外から何かを呼び出すと(問題のメソッドを 1 秒間に 50 回呼び出すと)、画面の一部がちらつくことがあります。すべてが間違っていると感じます。ここでの違いは何ですか?AWT バックエンドのソースを何らかの方法で管理されている場所まで掘り下げようとしましたが、非常に醜いコードから脳を救うためにそこで止めました。repaint()update(Graphics)JFramerepaint()EventQueuePaintEvent

また、全体について話し合うときrepaint()に、モデルの明確な変更に対応する画面の場所のみを再描画して、CPU/GPU の電力を節約するという「戦略」に行き着きました。これらのことを (アニメーションと同様に) 行うにはまだロジックが必要ですが、次の問題はFrameBuffer、レンダリングによって既に行われた作業を参照できるように、ペイントされた画面にどのように「アクセス」できるかです。

そして、はい、Java は、私たちが探しているすべての操作を最適な方法でサポートするプログラミング言語ではない可能性があるということを、すでに十分に耳にしています...

4

1 に答える 1

6

ここに私の質問があります: JFrame のバックエンドで paint(Graphics)、repaint()、および update(Graphics) を呼び出すと、画面にどのような違いがありますか? 「フレーム タイマー」から repaint() 以外を呼び出すと (問題のメソッドを 1 秒間に 50 回呼び出す)、画面の一部がちらつくことがあります。急速に)そしてすべてが間違っていると感じます。ここでの違いは何ですか?AWT バックエンドのソースを、PaintEvent が何らかの方法で管理されている EventQueue まで掘り下げようとしましたが、非常に醜いコードから脳を救うためにそこで止めました。

Swing での描画のスケジューリングは、 の責任ですRepaintManager。これは (特に) アプリケーションのどの領域を再描画する必要があるかを判断し、それらの更新を Event Dispatching Thread のコンテキスト内で発生するようにスケジュールする役割を果たします。

再描画がいつ発生するかは、完全に再描画マネージャー次第です。どの領域を再描画するかは、部分的には再描画マネージャー次第であり、再描画マネージャーは多数の再描画要求を 1 つの再描画イベントに統合して、時間と CPU を節約することもできます。

paint(Graphics)一般に、 orを呼び出すべきではありませupdate(Graphics)ん。グラフィック コンテキストを実際に作成できないという事実は別として、再描画マネージャーがこれを行います。画面を印刷したい場合でも、コンポーネントのprint(Graphics)メソッドを使用する必要があります。ダブル バッファリングされていないという事実は別として、バッファをネイティブ ピアにコピーして戻そうとすることに関連する問題があります ;)

paintちらつきは通常、の代わりにオーバーライドするなど、ダブル バッファリングされていないコンテキストからペイントしているために発生しますpaintComponent。一般的に言えば、paintトップレベルのコンテナのメソッドを実際にオーバーライドする必要があるのは非常にまれなケースです。JFrame

また、repaint() の全体について議論するとき、モデルの明確な変更に対応する画面の場所のみを再描画して、CPU/GPU の電力を節約するという「戦略」に行き着きました。これらのことを (アニメーションと同様に) 行うにはまだロジックが必要ですが、次の問題は、レンダリングによって既に行われた作業を参照できるように、ペイントされた画面の FrameBuffer にどのように「アクセス」できるかです。

通常、本当に必要でない限り、心配する必要はありません。再描画コードに注意している場合 (コンポーネント全体を再描画するのではなく、実際に領域を再描画するようにスケジュールすることができます)、実際に気にする必要はありません。メソッドの祖先をJComponent使用していることと、paintComponentメソッドを使用していることを確認してください。自動ダブルバッファリングが得られます...

もう1つの問題は、マウスの動きやコンポーネントのプロパティの変更などに応じて、コンポーネントがいつそれ自体の再描画を要求するかがわからないことです...

「フレーム バッファ」にアクセスすることは、おそらく本当に良い考えではありません。独自のバッファを生成し ( のようなものを使用BufferedImage)、それにレンダリングしてから、それを画面にレンダリングします (オフスクリーン バッファリング)。このようにして、独自の「FrameBuffer」を生成します

もしあなたが本当に絶望的であるならば、BufferStrategy

しかし、さらに深く掘り下げる前に、AWT と Swing でのペイントを参照することをお勧めします。これにより、ペイントがどのように機能するかをより深く理解できます。

また、自分がコントロールしているとは絶対に思わないでください。そうではありません。コントロールしようとする場合は、物事がすぐに爆発することに備えてください。プロセスを理解し、それに従って作業してください。

これらの(単純な)例を見てください...

于 2013-01-11T23:44:48.760 に答える