現在、ウィンドウに2次元グラフを表示しようとしています。
BMPなら、ファーマットもわかるので、
表示データ(BMPファイル)を作りながら、
ピクチャーボックスにロードしていますが、
重たくて、リアルタイムに表示できないのです。
画面がカクカクする...
何か、良い方法はありますか?
VB6として
プロジェクト→コンポーネントで
Microsoft Chart Control 6.0 (SPn)(OLEDB)
にチェックをつけてみて、追加されたコンポーネントを利用したらどうですか?
指摘されたコンポーネントを調べてみました。
が、やりたいこととちょっと違いそうです。
自分がやりたいことの説明が足りなかったようです。
やりたいこととして、
2次元グラフを表示するのですが、
X軸(横軸)は時間tとしており、サンプリング時間となります。
サンプリング中は、X軸が変化していきます。
そこで、リアルタイムにグラフが変動していくようにしたく。
指摘されたコンポーネントで実現できる。
だったら、こうした方がいいなど、
意見、ご助力をお願いします。
うーん、私が考える限りでは何らかの方法でグラフィックを(自力で)描くしか
無いような気がしますが、例えばPictureBoxにLineメソッドで描くとして、
・描く前にPictureBox.VisibleをFalseにする
・描く
・その後、PictureBox.VisibleをTrueにする
とかしてやれば、描いている途中の重たい描画処理が、描画終了後に一気に
やってくれるように変わりますので、格段に表示処理が速くなるかもしれません。
(出来れば、PictureBox.VisibleをFalseにする前に、できる限りの描画用の計算を
前もってやっておいた方が、VisibleがFalseとなる時間が短くなるので、
なお良いかもしれません)
私の場合、自力で時系列折れ線グラフのOCXを作成したことがあるんですが
(折れ線を全部Lineオブジェクトにしてしまったんで結構重いんですが……汗)、
OCXを使用するプロジェクト側でVisibleを変更しながら描画させると、Resizeしても
ちゃんと表示が追いつきます。
それに対して、VisibleがTrueのままで描画させると強烈に表示が遅く、Resizeした際に妙な動きになります(汗)。
どのような物にせよ、描画を行う処理の場合は、何らかの方法で一時的に描画を止めておいて
後で一気に描画したほうが、たいてい処理は速くなるようです。
タスクマネージャーのパフォーマンスタグのCPU使用率の履歴みたいなグラフですかね?
APIを使うのもありですか?
一度確定した情報(すぎた時間の分)は変化しないとして
ピクチャーボックスに表示しているデータを全部書き直すのではなく
BitBlt等をつかって変化のない値の部分はそのままずらしてコピーし
変化のあった部分だけ書き足す
とする事で、かなり改善できるとおもいますよ。
(ゲームなどのスクロール処理みたいな感じ)
そがっちさんが言ってるような方法もちらつき防止になります。
ご意見ありがとうございます。
そうです。
CPU使用率みたいなやつを自作したいのです。
To:そがっちさん
Lineメソッドなどは使用したことがあるのですが、
見栄えするグラフがかけず、断念した経緯があります。
そこで、BMPフォーマットで画像を作成してみました。
To:あんびさん
グラフをかけるAPIなどあるようでしたら、
ご紹介ください。
現在、BMPファイルを作成→表示→BMPファイルを作成→表示
を繰り返しています。
次のBMPファイルを作成する場合には、
以前の表示データをコピーするような形にしています。
・過ぎてしまった部分に関しては削除
・既存する部分に関してはデータコピー
・新しい部分の表示データを付加してます。
それで、時間を計測してるのですが、
BMPデータを作成するのには、時間がかかっていません。
クリティカルな部分としては、
・BMPデータをファイルに落とす
・BMPファイルをピクチャにロードする
です。
ピクチャに直接、BMPデータを送り込めれば早くなるかな
なんて思っています。
また、掲示板の主旨からずれてしまいますが、
VC++ならできるなどの意見もお待ちしております。
VC++でコントロール作って、インポートしてもいいと思うので...
すいません 自己レスです。
内部的には、表示したいデータを2次元配列で確保できてます。
(ドットのデータ?ピクセルのデータ?っていうんですかね)
その表示したいデータは常に確保してるので、
ピクチャボックスを使わなくても、
表示したいデータを直接渡すことができれば、
早くなるってことだと考えています。
・BMPのフォーマットでファイルとして保存する
・ファイルとして保存されたBMPのデータをピクチャに渡す
・ピクチャがBMPを解析して、表示するべきデータを作る
・それで、再描画してる
と考えると、表示したいデータをそのまま渡せることが
理想だと考えるのですが。
どうでしょう?
うーむ、確かにファイル経由だと、どうしても遅くなりますね……
何となく想像した限りでは、APIを使いまくって、メモリ上で
ビットマップを確保して内部的に描画する事は十分可能な気は するので、
頑張ればファイル経由しなくても出来るとは思います。
(細かい話は、私は詳しくはわからないし即答しかねますが)
最終的にビットマップをPictureに割り当てるのは……ハンドルあったら出来たっけか?(汗)
VB2005あたりなら標準で直接ビットマップ確保できるしGDI+使えるんで
楽なんですけどねぇ……
DIB(BITMAP)としてデータを保持しているのならば、単純にAPI関数の
SetDIBitsToDevice、伸縮させるのならばStretchDIBits辺りで描画させ
ればいいのでは。
事前にBITMAP用の領域を確保してなんとか、というのならば、API関数の
CreateDIBSectionでDIBSECTIONを作り、そのハンドルを
OleCreatePictureIndirectでPictureオブジェクトにして、中のデータを
書き換えた直後にRefreshメソッドを使うとか。
GDI+を使いながら云々というのならば、ふざけたサンプルで、
http://www.koalanet.ne.jp/~akiya/vbtaste/vbp/GDIPP020.lzh
というのも一応置いてあります。(未完成サンプル)
# GIFアニメを再生してみるとサンプルになるかも知れません。
これでどう?
http://support.microsoft.com/kb/183333/ja
あんびさん、ありがとうございます。
2次元グラフを表示できました。
さて、欲がでてきまして、
X軸とY軸の、目盛りを作りたくなってきました。
目盛り自体はあんびさんから紹介を受けた内容で、
できましたが、0や10などの数字を書きたくなりました。
何かいい手はないでしょうか。
ピクチャーボックスに目盛りは書かなくてもいいのではないですかね。
ラベルに目盛りを書いてピクチャボックス上に重ねるなりして表示したら
いいだけじゃないですか?
ちなみに目盛りが不定の場合、Indexゼロのコントロール配列のラベルを
1つだけ貼り付けておけば、実行時にIndexが1以上のラベルのコントロール配列を
Loadできるので、必要な数だけLoadして、プログラムで位置等の制御を掛ける、という手もありますよ。
但し、最終的に、ラベルのVisibleを強制的にTrueにしないと見えませんので
ご注意を。
(あと、1回目盛りを貼って終わりならいいですが、貼ったり剥がしたりを
繰り返す場合は、うまくUnloadも行ってください)
GDI32.DLLを調べ、
テキスト描画をすることで、
実現できました。
ツイート | ![]() |