我在TableLayoutPanel的顶部绘制了一个不断增长的矩形,但是当它增长时,即使使用Double Buffer也会导致可怕的闪烁。
我正在使用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();
}
为了排除所有其他可能性,我从程序中删除了所有内容,并从头开始只有一个不断增长的矩形,它仍然会产生这种可怕的闪烁。
答案 0 :(得分:3)
好的,这是代码。首先需要使用控件的大小制作后台缓冲区Bitmap。之后,您需要在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()
方法,以便永远不会调用base.OnPaintBackground
。这种方式根本不会有任何闪烁。你有闪烁的原因是因为你的Rectangle
之前的背景被重绘,无论你何时画出它。使用此TableLayoutPanel
BackgroundlessTableLayoutPanel
课程
public class BackgroundlessTableLayoutPanel : TableLayoutPanel
{
protected override void OnPaintBackground(PaintEventArgs e)
{
}
}
答案 1 :(得分:-1)
大多数控件都有一个Paint事件,您可以在其中实现您需要执行的任何自定义绘图。您可以在覆盖OnPaint方法的位置实现自己的控件。 See the article here
这两个都应该给出好的结果。