2

System.Drawing を使用して少しグラフを作成していますが、いくつかの問題があります。

私はキューにデータを保持しており、そのデータを 3 つのピクチャ ボックスに描画 (グラフ化) しています。

このメソッドは、画像ボックスを塗りつぶしてから、グラフをスクロールします。

前の図面の上に描画しないように (そして徐々に乱雑に見えるように)、グラフを描画するための 2 つの解決策を見つけました。

  1. plot.Clear(BACKGOUNDCOLOR)描画ループの前に呼び出す [ブロック コメント]

これにより、実際の描画ループを実行するのにかかる時間からちらつきが発生します。

  1. plot.DrawLine(channelPen[5], j, 140, j, 0);各ドローラインの直前に呼び出す [コメント]

これにより、描画は問題なく開始されますが、描画コマンドの前に待機コマンドが配置されたかのように、非常に急速に速度が低下します。

参照用のコードは次のとおりです。

/*plotx.Clear(BACKGOUNDCOLOR)

ploty.Clear(BACKGOUNDCOLOR)

plotz.Clear(BACKGOUNDCOLOR)*/

for (int j = 1; j < 599; j++)
            {
                if (j > RealTimeBuffer.Count - 1) break;

                QueueEntity past = RealTimeBuffer.ElementAt(j - 1);
                QueueEntity current = RealTimeBuffer.ElementAt(j);

                if (j == 1)
                {
                    //plotx.DrawLine(channelPen[5], 0, 140, 0, 0);
                    //ploty.DrawLine(channelPen[5], 0, 140, 0, 0);
                    //plotz.DrawLine(channelPen[5], 0, 140, 0, 0);
                }

                //plotx.DrawLine(channelPen[5], j, 140, j, 0);
                plotx.DrawLine(channelPen[0], j - 1, (((past.accdata.X - 0x7FFF) / 256) + 64), j, (((current.accdata.X - 0x7FFF) / 256) + 64));

                //ploty.DrawLine(channelPen[5], j, 140, j, 0);
                ploty.DrawLine(channelPen[1], j - 1, (((past.accdata.Y - 0x7FFF) / 256) + 64), j, (((current.accdata.Y - 0x7FFF) / 256) + 64));

                //plotz.DrawLine(markerPen, j, 140, j, 0);
                plotz.DrawLine(channelPen[2], j - 1, (((past.accdata.Z - 0x7FFF) / 256) + 94), j, (((current.accdata.Z - 0x7FFF) / 256) + 94));


            }

これらのオーバーヘッドを回避するためのトリックはありますか?

そうでない場合、他の/より良い解決策はありますか?

編集: ソリューション コードについては、以下の [最終的なソリューション] を参照してください。

4

5 に答える 5

4

PictureBoxではすでにダブルバッファリングがオンになっています。ちらつきを認識できる唯一の方法は、Paintイベントを使用する代わりに、画面に直接描画する場合です。スニペットから行うかどうかは明確ではありません。ビットマップを使用して自分自身をバッファリングすることもできますが、Windowsフォームによって実装されるダブルバッファリングほど効率的ではありません。

データが変更されたときにInvalidate()メソッドを呼び出し、Paintイベントで描画を実行します(e.Graphicsを使用)。ちらつきはありません。

于 2010-03-16T01:02:20.797 に答える
1

データを画像ボックスに入れる前に、データを別のビットマップにバッファリングしてみてください。これでちらつきが解消されます。

例えば:

// create this once for each graph
Bitmap buffer = new Bitmap({width}, {height});

// when the data changes
using (Graphics g = Graphics.FromImage(buffer))
{
    // ... draw using the graphics
}

// draw the buffer on the picture box's image

絵は別スレでやってる?1秒間に何回データを描画していますか? メイン スレッドで実行している場合、またはビットマップ全体を 1 秒間に何度も繰り返し描画している場合、プログラムは遅く感じられます。

于 2010-03-15T22:50:17.977 に答える
0

[最終的解決]

ループが重複していても、ペイント イベントを使用するのは十分に高速でした。

最後に、各イベントで描画ループを複製するのではなく、最初のイベントを使用して他の 2 つのグラフをビットマップに描画し、ペイント イベントで単純にビットマップを描画しました。

したがって、本質的に最終的な解決策は、あなたの多くの回答の組み合わせでした.

みんなありがとう。

private void pictureBoxAccX_Paint(object sender, PaintEventArgs e)
        {
            bufferedploty.Clear(Color.Black);
            bufferedplotz.Clear(Color.Black);           

            for (int j = 1; j < 599; j++)
            {
                if (j > RealTimeBuffer.Count - 1) break;

                QueueEntity past = RealTimeBuffer.ElementAt(j - 1);
                QueueEntity current = RealTimeBuffer.ElementAt(j);

                e.Graphics.DrawLine(channelPen[0], j - 1, (((past.accdata.X - 0x7FFF) / 256) + 64), j, (((current.accdata.X - 0x7FFF) / 256) + 64));
                bufferedploty.DrawLine(channelPen[1], j - 1, (((past.accdata.Y - 0x7FFF) / 256) + 64), j, (((current.accdata.Y - 0x7FFF) / 256) + 64));
                bufferedplotz.DrawLine(channelPen[2], j - 1, (((past.accdata.Z - 0x7FFF) / 256) + 94), j, (((current.accdata.Z - 0x7FFF) / 256) + 94));
            }   
        }


        private void pictureBoxAccY_Paint(object sender, PaintEventArgs e)
        {        
            e.Graphics.DrawImage(BufferedBitMapy, new Point(0, 0));            
        }


        private void pictureBoxAccZ_Paint(object sender, PaintEventArgs e)
        {            
            e.Graphics.DrawImage(BufferedBitMapz, new Point(0, 0));
        }




private void AddAccPoints()
        {
            //Code for putting in New queue data Here...
            pictureBoxAccX.Invalidate();
            pictureBoxAccY.Invalidate();
            pictureBoxAccZ.Invalidate();
        }

編集: この正確な解決策では、コントロールを無効にすると、イベント スケジューリングが未定義になり、ビットマップの作成がイベント メソッドの 1 つで行われるため、描画がランダムに停止する可能性があります。

ここを参照してください: Onpain イベント (無効) 期間の通常の操作 (実行時) 後に実行順序を変更する

于 2010-03-16T10:24:57.580 に答える
0

ピクチャ ボックスをサブクラス化し、ダブル バッファ オプションを有効にします。

Public Class MyBufferedPictureBox Inherits System.Windows.Forms.PictureBox

Public Sub New()
    MyBase.New()

    Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
End Sub

クラス終了

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.setstyle.aspx

于 2010-03-15T23:02:45.843 に答える
0

私はダブルバッファアプローチを使用します。メモリ内に新しいビットマップ (グラフと同じサイズ) を作成し、そのビットマップのグラフィックス オブジェクトを作成します。

次に、そのオブジェクトに必要なものを描画します。

すべての描画が完了したら、pictureBox から別のグラフィックス オブジェクトを作成し、DrawImage を使用してメモリ内ビットマップを描画します。

画像全体を更新する1つの大きな描画を除いて、画面のすべてを描画するため、これによりちらつきが軽減されます。

それが役に立てば幸い。

于 2010-03-15T22:58:09.873 に答える