-1

比較的単純な Windows アプリケーションがあります。約 15 のコントロールを使用します。

私のコンストラクターメソッドは次のようになります。

public Form1()
{
    InitializeComponent();
    this.Paint += this.Teken;
}

私の Teken メソッド (簡略化) は次のようになります。

private void Teken(object o, PaintEventArgs pea)
{
    if (start)
    {
        if (comboBox1.Text == "Basic")
            Bitmaps.DrawBitmap1(pea.Graphics, bitmapsize, max);
    }
}

私の DrawBitmap1 メソッドは、すべてのピクセルに特定の色を設定し、Graphics.DrawImage メソッドを使用してビットマップを描画します。

ビットマップが描画された後、コントロールが非常に遅くなり、テキスト ボックス内のテキストを選択するのに 1 秒以上かかります。メインフォームは本当に遅くなります。

ビットマップがゆっくり描画されることは理解できますが、これは理解できません。

私の問題に対する簡単な解決策はありますか?

編集:

Drawbitmap1 コードは次のとおりです。

public static void DrawBitmap1(Graphics gr, int bitmapsize, int max)
    {
        Bitmap bitmap1 = new Bitmap(bitmapsize, bitmapsize);

        for (int x = 1; x < bitmapsize; x++)
        {
            for (int y = 1; y < bitmapsize; y++)
            {
                int mandelnumber = CalculateMandel(x,y)

                if (Form1.mandelnumber == max) 
                    bitmap1.SetPixel(x, y, Color.Black);
                else if (Form1.mandelnumber %2 == 0) 
                    bitmap1.SetPixel(x, y, Color.White);
                else 
                    bitmap1.SetPixel(x, y, Color.Black);
            }
        }
        gr.DrawImage(bitmap1, 50, 100);
    }

mandelnumber は、プログラムの別の部分で計算される変数です。

EDIT2:

プロファイラーを実行しましたが、ビットマップのすべてのピクセルを通過した後も CalculateMandel() メソッドの実行が停止しないようです。これはどのように可能ですか?

EDIT3:

テキストボックスまたはボタンにカーソルを合わせると、DrawBitmap1 関数が再度呼び出されることが判明しました。どうすればこれが可能になるのですか?ホバーイベントはなく、TextChangedイベントもありません..

4

3 に答える 3

1

あなたのDrawBitmap1方法は、おそらく、ソースが何であれ、ビットマップが描画面でサポートされているものであれば、何らかのレベルの変換です。それは、異なる色密度、異なるビット密度などである可能性があります(おそらくスケーリング?)。通常、それには少し余分な時間がかかります。

PictureBox代わりにコントロールを使用することをお勧めします。

さらに、表示したい画像を再描画する必要がある場合は、画面を描画/ペイントするときではなく、画像が変更されたときにのみ実行することをお勧めします.これはパフォーマンスの低下につながります. 例えば

pictureBox.Image = DrawBitmap1(gr, bitmapSize, max);

画像を 1 秒間に数回以上変更する場合は、SetPixel を使用しないことをお勧めします。画面を更新するのに十分なパフォーマンスが得られないためです。

ペイントで行う際の問題は、痛みが発生したときとビットマップを変更する必要があるときが常に同じではないことです。ビットマップを変更する必要がある場合はフォームを更新できますが、フォームの他のすべての描画ではパフォーマンスが低下します。

于 2012-09-22T17:53:04.160 に答える
1

フォームが再描画されるたびに、非常に高価な O(n2) アルゴリズムが実行されますが、そのアルゴリズムはあまり最適化されていません。

一度だけ実行する必要がある多くの冗長な作業を行っているように見えます。あなたのDrawBitmap1関数は、3 つの画像のうちの 1 つを生成します (表示することさえないビットマップに、そうですか?)。

内側のループから if ステートメントを取り出して、3 つのバージョンを作成することもできます。反復間で変化しないため、同じ条件を何度もチェックする必要はありません。

各イメージを一度作成してキャッシュすることができます。その画像が再び必要な場合は、関数から直接返すだけです。

その上、GDI+の関数GetPixel()と関数は非常に遅いです。SetPixel()つまり、本当に、本当に遅いです。.NET での実際の画像処理は、メモリへの直接ポインターを使用して安全でないコンテキストで実行される可能性があります。オブジェクトBitmap.LockBitsを返す を呼び出し、プロパティを使用してメモリ バッファーへのポインターを取得します。BitmapDataScan0

于 2012-09-22T18:11:27.810 に答える
1
this.Paint += this.Teken;

これは間違ってTekenいます。アプリの再描画が必要になるたびにルーチンが呼び出されます。ウィンドウを開くとき、ウィンドウのサイズを変更するとき、フォーカスを変更するとき、別のウィンドウを移動するとき、ツールチップを取得するとき、解像度やテーマを変更するとき、ほぼ常に。実際、Teken呼び出されないのCalculateMandelは が終了して結果を表示する必要があるときだけです。電話をかけInvalidateないので、結果を描画する必要があるときにアラートが表示されることはありません。

...CalculateMandel()ビットマップのすべてのピクセルを通過した後も実行を停止しません。これはどのように可能ですか?

UIで何かが変更されるたびに、ビットマップ内のすべてを再計算するように具体的に指示しているためです。何度も何度も。ビットマップだけが変更されない限り、再描画するように指示しません。完全に後退。また、再描画が必要ない場合でも、ビットマップを無駄に再計算しているため、UI がロックされます。

...DrawBitmap1テキストボックスまたはボタンにカーソルを合わせると、関数が再度呼び出されます。これはどのように可能ですか、ホバーイベントはありません

しかし、別の何かがあります。おそらくツールチップ。CalculateMandel()また、アプリの UI (ビットマップを除く) が変更されるたびに呼び出すようにアプリに指示しました。

問題は、2 つのまったく別のことが起こっていることです。何かが変更されたときにアプリで UI を再描画する必要があり、CalculateMandel()完了時に UI を更新する計算 ( ) があるとします。これらは個別のイベントであり、個別に処理する必要があります。

this.Paint += this.Teken;まず、 ;を取り除きます。それはあなたの問題を引き起こし、あなたが望むことをしません。

次に、そのイベントBackgroundWorkerで呼び出すを作成し、イベントで完成したビットマップを返し、新しいデータを再描画するために呼び出します。CalculateMandel()DoWorkProgressChangedyourWindowOrPanelOrWhatever.Invalidate()

于 2012-09-22T21:00:17.997 に答える