C #, двойной буфер в WinForms? - PullRequest
       42

C #, двойной буфер в WinForms?

2 голосов
/ 23 февраля 2011
        private void button3_Click(object sender, EventArgs e)
    {

        this.DoubleBuffered = true;

            for (int i = 0; i < 350; i++)
            {
                using (Graphics g = this.CreateGraphics() )
                {
                    g.Clear(Color.CadetBlue);
                    g.DrawImage(Properties.Resources._256, 100, 100, i-150, i-150);
                }
            }
    }

И все же я подумал, что для DoubleBuffered установлено значение true, изображение все еще мигает. Есть идеи, что я делаю не так? Спасибо!

Ответы [ 3 ]

6 голосов
/ 23 февраля 2011

Как отметил Нейл, вам не нужно (и не нужно) создавать новый объект Graphics в каждой итерации цикла.Это относительно дорогие ресурсы, и их не следует создавать невольно.

Кроме того, вы не должны рисовать так внутри обработчика нажатия кнопки, вызывая CreateGraphics.Это может привести к проблемам, особенно к тому, что ваш рисунок «отменяется», когда вызывается обработчик рисования (т. Е. Каждый раз, когда окно получает сообщение WM_PAINT и обновляется).Вы должны сделать все свои рисунки, переопределив OnPaint и просто вызывая Invalidate (), когда вам нужно обновить форму.

Что касается мерцания, то установка DoubleBuffered в значение true обычно позаботится об этом, но переходя на собственноедвойная буферизация тривиальна.Попробуйте.Также поймите, что рисование в таком цикле, вероятно, не то, что вы хотите делать.Используйте таймер, если вы хотите обновить один раз за некоторый интервал.Ваш код выполняется так быстро, как может выполняться цикл, что обычно нежелательно.

private void someTimer_Tick( ... )
{
    Invalidate();
}
protected override void OnPaint( PaintEventArgs e )
{
    using( var tempBmp = new Bitmap( ... ) )
    using( var g = Graphics.FromImage( tempBmp ) )
    {
        // draw to tempBmp
        e.Graphics.DrawImage( tempBmp, new Point( 0, 0 ) );
    }
}
2 голосов
/ 23 февраля 2011

Двойная буферизация включена только для события Paint. Вы непосредственно рисуете на экран с помощью CreateGraphics (), вызов g.Clear () очень заметен, поскольку он мгновенно стирает нарисованное изображение. Не рисование в событии Paint или методе OnPaint почти всегда является ошибкой.

2 голосов
/ 23 февраля 2011

Проблема в том, что вы создаете новый графический объект на каждой итерации цикла

Переместите оператор for в оператор using, и вы увидите резкое увеличение производительности:

using (Graphics g = this.CreateGraphics() )
{
     for (int i = 0; i < 350; i++)
     {
        g.Clear(Color.CadetBlue);
        g.DrawImage(Properties.Resources._256, 100, 100, i-150, i-150);
     }
}

Это также может быть хорошей идеей для перемещения файла ресурсов, который вы загружаете, в локальную переменную.

...