- PR -

効率の良い描画方法とは?

投稿者投稿内容
ボム
ベテラン
会議室デビュー日: 2003/07/25
投稿数: 61
投稿日時: 2003-08-19 09:01
ほむら様、Ken-Lab様、ご意見ありがとうございました。

ほむら様より引用***************************************************************
>changeImage()はsyncronized(?)で同期が取れるようになっていますか?
マルチスレッドではない(フォーカスの有るパネルだけのスレッドが走るので複数同時にスレッドが走る事は無いの意味)ので"syncronized()"は必要ないと考えていますがどうでしょうか?

>画像を更新している最中にスレッドの画面更新が入っているようなそんなイメージがちらほら
>と。。。。
もう少し具体的に教えていただけませんか?
******************************************************************************

Ken-Lab様より引用**************************************************************
>読み込む画像フォーマットはどんな形式でしょう?
Gifです。
******************************************************************************

ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-08-19 10:20
ども、ほむらです。
自分でもつくってみようとがんばっていますが、
コンパイルすら通りません^^;;;;;;;
-----------------
Casper氏へ
引用:

>changeImage()はsyncronized(?)で同期が取れるようになっていますか?
マルチスレッドではない(フォーカスの有るパネルだけのスレッドが走るので複数同時にスレッドが走る事は無いの意味)ので"syncronized()"は必要ないと考えていますがどうでしょうか?

>画像を更新している最中にスレッドの画面更新が入っているようなそんなイメージがちらほら
>と。。。。
もう少し具体的に教えていただけませんか?


ケースの流れを考えた場合、
キーボードを押すタイミングがゆっくりならば平気だけど
ずっと押しつづると画像が崩れてしまうということですよね?。

このときの処理を考えてみると。
1.フォーカスの取得
    画像変更→画面更新→スレッド起動

thread.run()の起動
    座標移動→画面更新

2.フォーカスの喪失
    画像の変更?→スレッドの停止  画面更新はコメントアウト?

といった流れになるのでしょうか?
これが瞬間的に何度も流れますよね?

シロウト考えにrun()の実行中にフォーカスの取得と喪失が発生した場合は?
なんてことを考えてしまうのですが・・・
普通の状態では画像の書き込みに50msかかるなんてこと考えられませんが
昔のJAVAは画像処理が遅いといった話を聞いたことがあります。

あとは
Winアプリのようにイベントドリブンのようで実は上から下に
発生した順に処理しているのならともかく、
変にマルチでイベントの複数同時もありえるなんて場合は
フォーカスの取得と喪失が同時なんてことも。。。。

長くなりましたがこんな場合を思ったときに
オフスクリーンからプライマリスクリーンに書き込もうとしたとき
オフスクリーンに別の画像を書き込んでいる最中だったら
変更中の画像をプライマリに書き込んでしまうわけで。。。

offGraphicsもメンバ変数で共有しているみたいですし。。。
paint()の中で宣言してdispose()?してあげたらまた別の結果が出てこないかな〜
とも思ってみたり。。。

あと、もう一点。。。
オフスクリーンの画像をクリアしているだけなのにちらつくというのも
おかしな話ですね。
たしかJAVAにもsleep関数ってありましたよね?
offGraphics.clearRect() のあとに 5msくらいスリープしてみては?

# やってみたいことはいろいろあるのにプログラムが〜(涙
# あれ?よく考えたらオフスクリーン→プライマリスクリーンの部分も
# synchronized 関数にしないと結局一緒?ん???


#名前が間違えていたのと言い忘れの追加
#さらに微妙に修正


[ メッセージ編集済み 編集者: ほむら 編集日時 2003-08-19 12:00 ]
ボム
ベテラン
会議室デビュー日: 2003/07/25
投稿数: 61
投稿日時: 2003-08-19 11:23
ほむら様、ご意見ありがとうございました。

ほむら様より引用****************************************************************
>キーボードを押すタイミングがゆっくりならば平気だけど
>ずっと押しつづると画像が崩れてしまうということですよね?。

ずっと押しつづけると絶対に画像が崩れる(新しい文字列が古い文字列と重なる)わけではなく、ずっと押しつづけても崩れない場合も有るのです。(これが厄介・・・)

前に載せたpaint()メソッドを見ていただいてわかってらっしゃるとは思いますが、
最初にオフスクリーンに背景画を張ります、次に文字列を張り、描画。
次の描画もオフスクリーンに背景画を張るので、背景画を張った時点で古い文字列は背景画に消されるのではと思ったのですが・・・

ほむら様の書かれた処理の流れは、その通りだと思います。
しかし、このアプリケーションを起動するマシンによって崩れたり、崩れなかったりが発生するのはやはりマシンの性能が原因なのでしょうか?
つまり性能が良いと処理の流れについていけるが、性能が悪いとついていけず描画が崩れてしまう。
******************************************************************************

paint()メソッドを書き直したのですがどうでしょうか?
setClip()を使って文字列の動く範囲を制限しました。
それがちらつきと関係あるでしょうか?

public void paint(Graphics g) {
  if (offImage == null) { // 起動時
   offImage = this.createImage(sizePanelW, sizePanelH);
   offGraphics = offImage.getGraphics();
   //パネルイメージを描画
   switch(im_status) {
    case 0:
     main_img = im_normal;
     break;
    case 1:
     main_img = im_select;
     break;
    case 2:
     main_img = im_target;
     break;
   }
   offGraphics.drawImage(main_img, 0, 0, this);
   //オフスクリーン描画
   g.drawImage(offImage, 0, 0, this);
  } else { // 復活作業
   offGraphics.clearRect(0,0,sizePanelW, sizePanelH)
   //パネルイメージを描画
   offGraphics.setClip(0,0,sizePanelW,sizePanelH);
   offGraphics.drawImage(main_img, 0, 0, this);
   //パネルタイトル描画
   offGraphics.setColor(Color.black);
   offGraphics.setFont(TitleFont);
   offGraphics.setClip(posiClipX, posiClipY, sizeAClipW, sizeClipH);
   offGraphics.drawString(Number, posiNumberX, posiNumberY);
   //オフスクリーン描画
   g.drawImage(offImage, 0, 0, this);
  }
}


未記入
大ベテラン
会議室デビュー日: 2003/06/28
投稿数: 219
投稿日時: 2003-08-19 12:14
こんにちは。ちょっと確認したいことがありまして・・・。
# 勘違いでしたらスミマセン。
引用:

Casperさんの書き込み (2003-08-06 16:42) より:
・フレームの上にパネルが10枚あり各パネルに絵を張りその上に文字列を書いております。


この10枚のパネルは、一つの画面上に同時に表示されているという解釈でよろしいでしょうか?
もしそうであるとして、paintメソッドも10コ独立して動いているわけではないですよね?
# 200*30 サイズのGIF表示であるなら、マシンのリソース不足だけとは考えにくい・・・。

[ メッセージ編集済み 編集者: Ken-Lab 編集日時 2003-08-19 12:33 ]
# 考えなくい → 考えにくい

[ メッセージ編集済み 編集者: Ken-Lab 編集日時 2003-08-19 14:09 ]
ボム
ベテラン
会議室デビュー日: 2003/07/25
投稿数: 61
投稿日時: 2003-08-19 13:44
Ken-Lab様、ご意見ありがとうございました。
私の説明下手をお詫びします。m(_ _)m

Ken-Lab様より引用***************************************************************
Ken-Lab様の質問の答えになってなかったらすみません。
>この10枚のパネルは、一つの画面上に同時に表示されているという解釈でよろしいでしょう
>か?
はい、そうです。

>もしそうであるとして、paintメソッドも10コ独立して動いているわけではないですよね?
パネルを継承したクラスを作成して、その配列をパネル分(10個)作成してあります。
ですから、paint()は各パネルに独立してあると考えます。

個々のパネルのクラス↓
*public class Panel_Album extends Panel implements Runnable{
明記したpaint()メソッドやupdate()、スレッドなどはこのクラス内の関数です。

上記のクラスを別クラスで配列で定義したのが↓
*public Panel_Album[] pnlAlbum;


我ながら、わかりにくい説明だぁ・・・



ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-08-19 13:57
ども。。。
自宅に帰るまでは昨日の続きは出来ないほむらです。
---------------------
Caspre氏へ
clearRect()をpaint()内部に入れるとちらつくことと
画像が崩れてしまう現象は原因として同じだという可能性が高いです。
(新しい画像を表示する変わりにクリアしているのでちらついて見える)

そこで、実験してみてほしいのですが。。。
1.clearRect()をフォーカス喪失時の先頭または
  changeImage()の先頭に書き込む(移動する)のと
  # ↑透明色を使っていてなければの話です

2.repaint()をchangeImage()の内部に統一してみてください。
  # =repaint()が呼び出されるのは
  # run(),changeImage() の 2箇所のみになります。

setClip()はoffImage==nullの時またはフォーカス取得時のみでいいような気もします。
(文字の部分はclipRect()でなくていいんですかね?)
# 使い方わかってません^^;;;;
# あと文字を描く部分が同じならば
# 最大の領域で一度だけのほうがいいかも

時間があれば synchronized で同期をとる形にして
paint()のelseの部分を別の関数にするのと
changeImage()を変更してみてください。
# でももしかしたら、
# offImage.flush(); // こんな使い方してもいいのか不明^^;;;
# g.drawImage(offImage, 0, 0, this);
# だけでもいいのかも??

# マシンパワーのせいとは思いたくないですね。。。
# 勘違いの部分を修正

[ メッセージ編集済み 編集者: ほむら 編集日時 2003-08-19 14:08 ]
未記入
大ベテラン
会議室デビュー日: 2003/06/28
投稿数: 219
投稿日時: 2003-08-19 14:15
引用:

Casperさんの書き込み (2003-08-19 13:44) より:
>もしそうであるとして、paintメソッドも10コ独立して動いているわけではないですよね?
パネルを継承したクラスを作成して、その配列をパネル分(10個)作成してあります。
ですから、paint()は各パネルに独立してあると考えます。


ハイ、イメージが湧きました。そして、updateメソッドの効果がない理由がここにあるのでは、
と考えます。このような使い方をしたことがないので以下仮説ですが、バッファリング
できるのは、それぞれのメソッド自身が書き出したものに限られ、残りの9枚は
バッファリングされないのが原因ではないか、と考えます。
できればひとつのpaintメソッドに纏めるか、何らかの同期処理をする必要があるのでは
ないでしょうか。

# ひとつのpaintメソッドという表現では紛らわしいと思われますので追記しますが、
# これは10枚のパネルをpaintメソッド内で一気に描いてしまう、という意味です。

[ メッセージ編集済み 編集者: Ken-Lab 編集日時 2003-08-19 21:50 ]
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2003-08-19 14:25
paint()メソッドのelse節とanimation-threadで画像の位置を変更している箇所を
共通のオブジェクトでロック(synchronized節で囲む)してやらないといけないかもしれません。

 不確かな記憶で申し訳ないですが、現在のJVMのメモリモデルはthreadが起動すると作業用の専用にメモリ領域を確保し、threadはその作業領域に対して変更を行います。
 このことが原因して、画像が崩れたりしているのではないでしょうか?
解決法として、上述したように、同期を取り、作業領域をメイン領域に書き戻してやります。

JVMのメモリモデルについては、理解しきれていないので、識者の方フォローをお願い致します。

スキルアップ/キャリアアップ(JOB@IT)