0

我在 TableLayoutPanel 上绘制了一个不断增长的矩形,但是当它增长时,即使使用双缓冲区也会导致可怕的闪烁。

我正在使用 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();
    }

为了排除所有其他可能性,我从程序中删除了所有内容,并从头开始,只有一个不断增长的矩形,它仍然会产生这种可怕的闪烁。

4

2 回答 2

3

好的,这里是代码。您首先需要使用控件的大小制作背景缓冲区位图。之后,您将需要在位图上绘制所有内容,然后将该位图绘制到控件上。

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,任何时候你绘制它。用这个切换原来的TableLayoutPanelBackgroundlessTableLayoutPanel

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

    }
}
于 2013-06-18T10:49:54.253 回答
-1

大多数控件都有一个Paint事件,您可以在其中实现您需要执行的任何自定义绘图。也可以在覆盖OnPaint方法的地方实现您自己的控件。请参阅此处的文章

这两个都应该给出好的结果。

于 2013-06-18T10:09:21.870 回答