編集:解決しました、私の解決策を以下で見てください。
まず、これが私の最初の質問ですので、間違えた場合は教えてください。
トレーニング目的で、Javaでマンデルブロフラクタルプログラムを作成しようとしています。私が欲しいすべての機能にとって理想的なのはFractalizer(http://www.fractalizer.de/en/)ですが、今のところ、(代わりに)画面にマンデルブロ集合を描画するプログラムに満足しています。 、たとえば、画像ファイルへの書き込み)。もちろん、プログラムを高速にしたいので、計算を複数のスレッドに分割して、マルチコアプロセッサを利用できると思いました。たとえば、クアッドコアシステムでは、画像は2x2 = 4の画像に分割され、それぞれが個別のスレッドによって計算されます。これらのスレッドはすべて、計算時にピクセルを描画するGraphicsオブジェクトを取得します。
これを機能させるための最初の試みは、スレッドをBufferedImage.getGraphics()に描画させ、画像が完成していない限り、paint()メソッドが常にrepaint()を呼び出すようにすることでした。
g.drawImage(tempImg, 0, 0, null);
if (waiterThread.isAlive())
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
// do nothing
}
repaint(10);
}
(waiterThreadは、すべての計算スレッドを次々に結合します。waiterThreadが有効である限り、少なくとも1つの計算スレッドはまだ終了していません。)
これは機能しますが、頻繁に再描画されるため、キャンバスに醜いちらつきが発生します。
次に、小さなテストプログラムを使用して、Graphics.draw * anything *が、paintメソッドが戻る前に画面に即座に描画されることを発見したので、現在のアプローチは次のとおりです。
- 2x2(<4コアシステムでは1x1)のMandelbrotCanvasオブジェクトを含むGridLayoutを備えた1つのパネル
- 各MandelbrotCanvasオブジェクトは、最初のpaint()呼び出しで、計算スレッドを初期化し、独自のGraphicsオブジェクトを渡します(実際には、1つのGraphics呼び出しを複数のグラフィックに渡すカスタムGroupGraphicsクラスを使用して、画像をBufferedImage.getGraphics()に入れますが、これは重要ではありません)、計算スレッドを開始します。
- パネルは、paint()メソッドで、各MandelbrotCanvasesから計算スレッドをフェッチし、それらをjoin()します。
残念ながら、これは黒い画面しか作成しません。計算が終了した場合のみ、画像が表示されます。
複数のスレッドを1つのコンポーネントにペイントする正しい方法は何ですか?
編集:
私が知らなかったこと:イベントディスパッチスレッドのみがAWTコンポーネントにペイントすることを許可されています(大まかに話されています)。つまり、上記の最後のアプローチはおそらく機能しない可能性があります-明らかに、例外をスローすることになっていますが、私はしませんでした1つ取得します。私の解決策は、最初のアプローチを使用することです-画像をBufferedImageに描画し、それをCanvasに描画します-唯一の変更は、update()メソッドをオーバーロードして、ペイント領域をクリアせずにpaint()メソッドを呼び出すことです。
public void update(Graphics g)
{
paint(g);
}
したがって、一般的な質問(「複数のスレッドをAWTコンポーネントにペイントさせるにはどうすればよいですか?」)に対する私の答えは次のようになると思います。できません。許可されていません。スレッドがBufferedImage.getGraphics()に描画し、その画像を繰り返し描画します。ちらつきを避けるために、上記のようにupdate()メソッドをオーバーロードします。(今は本当に素晴らしいように見えます。)私の場合は使用できませんが、それでも良いもう1つのヒントは、再描画する必要のある領域を指定するために長方形の引数を取るrepaint()のバリアントがあることです。時間引数(ミリ秒単位)をとるバリアント。したがって、再描画をすぐに実行する必要はありません。
EDIT2:このリンクは非常に役立つ情報を提供します:http://java.sun.com/products/jfc/tsc/articles/painting/index.html