2013-06-18 2 views
0

У меня есть растущий прямоугольник, нарисованный поверх TableLayoutPanel, но когда он растет, он вызывает ужасное мерцание даже при использовании Double Buffer.Growing Rectangle

Я использую e.Graphics.FillRectangle и глобальную переменную, которая увеличивает размер прямоугольника. Я настроил таймер, чтобы он увеличивался каждые 1/10 секунды на 1 пиксель. Почему это мерцает так много, и как я могу остановить мерцание?

int grow = 100; 
    private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e) 
    { 
     e.Graphics.FillRectangle(Brushes.Red, (tableLayoutPanel1.Width-grow)/2, (tableLayoutPanel1.Height-grow)/2, grow,grow); 
    } 

    private void timer1_Tick(object sender, EventArgs e) 
    { 
     grow += 10; 
     tableLayoutPanel1.Refresh(); 
    } 

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

+2

могли бы вы предоставить код? Установка DoubleBuffer истина не помогает всегда. –

+0

Несомненно, я постараюсь упростить код, поэтому вы не получите прицепной повсюду, думая, что проблема находится где-то в другом месте. – CodeCamper

+0

Nikola добавил код, просто создайте Timer и TableLayoutPanel и введите код в новый проект, и вы увидите мерцание. – CodeCamper

ответ

3

Хорошо, вот код. Сначала вам нужно создать фоновый буфер Bitmap с размером вашего элемента управления. После этого вам нужно будет нарисовать все на растровом изображении, а затем нарисовать это растровое изображение на элементе управления.

Bitmap backBuffer = null; 
int grow = 100; 
private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e) 
{ 
    if (backBuffer == null) 
     backBuffer = new Bitmap(tableLayoutPanel1.Width, tableLayoutPanel1.Height); 
    Graphics g = Graphics.FromImage(backBuffer); 
    g.Clear(tableLayoutPanel1.BackColor); 
    g.FillRectangle(Brushes.Red, (tableLayoutPanel1.Width - grow)/2, (tableLayoutPanel1.Height - grow)/2, grow, grow); 
    e.Graphics.DrawImage(backBuffer, 0, 0, backBuffer.Width, backBuffer.Height); 
    g.Dispose(); 
} 
private void tableLayoutPanel1_Resize(object sender, EventArgs e) 
{ 
    backBuffer = null; 
} 
private void timer1_Tick(object sender, EventArgs e) 
{ 
    grow += 10; 
    tableLayoutPanel1.Invalidate(); 
} 

Обратите внимание, что вам нужно будет создать новый Bitmap каждый раз, когда вы изменяете размер TableLayoutPanel. Кроме того, я предлагаю использовать Invalidate() вместо Refresh().

Но это все равно будет включать некоторые потенциальные мерцания. Чтобы полностью избежать мерцания, в дополнение к предыдущему коду вам нужно подклассифицировать TableLayoutPanel и переопределить метод OnPaintBackground() таким образом, чтобы никогда не вызывался. У этого пути вообще не будет никаких мерцаний. Причина, по которой вы мерцаете, - это то, что фон перерисовывается перед вашим Rectangle, когда вы его рисуете. Включите оригинальный TableLayoutPanel класс с этим BackgroundlessTableLayoutPanel

public class BackgroundlessTableLayoutPanel : TableLayoutPanel 
{ 
    protected override void OnPaintBackground(PaintEventArgs e) 
    { 

    } 
} 
+0

Мне понравилось изучать эту концепцию нового растрового буфера, но, похоже, вы попали в настоящий гвоздь прямо на голову. «OnPaintBackground» запускает метод Paint и вызывает мерцание, которое не связано с производительностью. Не могли бы вы подробнее рассказать о том, как вы измените OnPaintBackGround, потому что когда я это делаю, я вижу замороженную копию моего рабочего стола в моей форме. – CodeCamper

+0

Отключение OnPaintBackground имеет много непредвиденных последствий, но это корень проблемы, так что лучший способ решить эту проблему? Если я просто отключу его, то перетаскивание моей формы с экрана создаст эффект заморозки и дублирует фон ... – CodeCamper

+0

Каждый раз очищайте растровое изображение с каким-то фоновым цветом перед рисованием прямоугольника, чтобы буферный буфер мог служить фоном. –

-1

Большинство элементов управления имеет событие Paint, где вы можете выполнить любой пользовательский чертеж, который вам нужно сделать. Также можно реализовать собственный контроль, где вы переопределяете метод OnPaint. See the article here.

Оба они должны давать хорошие результаты.

+0

Нет, им это не нужно, если панель перерисовывает свой фон, на более медленных компьютерах вы можете ощутить мерцание, рисование в обратном буфере памяти может решить проблему. Кроме того, поскольку OP использует e.Graphics, я предполагаю, что он уже использует обработчик событий Paint. –

+0

Отлично, Отлично, Хорошо, Посредственно, [ok], Плохо. Теперь мне просто нужно удалить мерцание. Nikola, я был бы признателен за помощь в использовании растрового изображения, чтобы удалить это мерцание, поскольку я пытаюсь сделать небольшую динамическую анимацию в моей winform. – CodeCamper