【问题标题】:How do I double buffer a Panel?如何双缓冲面板?
【发布时间】:2010-10-23 12:52:04
【问题描述】:

我有一个面板,上面有一个轮盘,我需要对面板进行双重缓冲,使其停止闪烁。谁能帮帮我?

编辑:

是的,我试过了。

panel1.doublebuffered 不存在,只有 this.doublebuffered。而且我不需要缓冲表单,只需缓冲面板。

【问题讨论】:

  • 面板 does 有一个 DoubleBuffered 属性(JP 链接到它的文档)。请注意,该属性受到保护,这就是您无法访问它的原因。创建一个 Panel 的子类,并在构造函数中设置它。
  • 也许这对其他人来说不是问题,但是在InitializeComponent中设置值会导致设计器崩溃;正如@Andy 所说,在构造函数中进行。

标签: c# winforms doublebuffered


【解决方案1】:

我和你一样的困境。我在 C# WinForm 中放置了一个面板,并将其用作几何动画的显示区域。由计时器触发的多次重绘操作,再加上偶尔调整窗口大小,都导致该面板严重闪烁。这里提供的其他解决方案似乎都依赖于激活DoubleBuffered 标志,但这对我的体验没有任何影响。

正确的方法是使用System.Drawing.BufferedGraphics 类并在您的应用程序中使用它。

这里有一个overview,还有一个真正有效的example(不再闪烁!)。

这个例子有点矫枉过正,因为它至少突出了两种在翻转图形缓冲区之前执行渲染的方法;你只需要在你的实现中保留你喜欢的那个。

我个人选择将 Panel 子类化为一个新的 DoubleBufferedPanel 类。我只是使用基本 Panel 的 Paint() 方法结合对 Refresh() 的调用来翻转缓冲区。

【讨论】:

    【解决方案2】:

    只是扩展 User79775 的答案,如果您想在 VB.net 中实现这一点,请这样做:

    Imports System.Windows.Forms
    
    Public Class MyDisplay
        Inherits Panel
    
        Public Sub New()
            Me.DoubleBuffered = True
    
            ' or
    
            SetStyle(ControlStyles.AllPaintingInWmPaint, True)
            SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
            UpdateStyles()
        End Sub
    End Class
    

    【讨论】:

      【解决方案3】:

      另一种方法是调用双缓冲成员,使用 InvokeMember 方法:

       typeof(Panel).InvokeMember("DoubleBuffered", BindingFlags.SetProperty    
                  | BindingFlags.Instance | BindingFlags.NonPublic, null,
                  panel2, new object[] { true }); 
      

      通过这种方式,您不必创建子类

      【讨论】:

      • 这是一个很好的解决方案。准确地说你必须把它放在 InitializeComponent(); 之后在您视图的构造函数中。
      • 通过反射设置受保护的属性很难看吗?是的。子类化你想在 GUI 设计器中使用的控件是否更丑陋?也可以。
      【解决方案4】:

      您可以在Panel 的派生类中公开DoubleBuffered-Property:

      public class DoubleBufferedPanel : Panel
      {        
          [DefaultValue(true)]
          public new bool DoubleBuffered
          {
              get
              {
                  return base.DoubleBuffered;
              }
              set
              {
                  base.DoubleBuffered = value;
              }
          }
      }
      

      【讨论】:

      • 因为除了 with 双缓冲之外,使用这个类没有任何意义,我会让它更简单:class DoubleBufferedPanel: Panel { public DoubleBufferedPanel(): base() { DoubleBuffered = true; } }.
      • 确实很简单。在我的项目中添加了这一行之后,我所要做的就是去设计器并在两个地方更改相关面板的数据类型,现在一切都很好......非常酷!
      【解决方案5】:

      Winform 面板有一个DoubleBuffered property

      编辑:我应该注意到它受到保护。其他人已经描述了如何对其进行子类化。 :)

      【讨论】:

        【解决方案6】:

        您需要从 Panel 或 PictureBox 派生。

        这取决于您选择启用缓冲的方式。

        如果你设置了 this.DoubleBuffer 标志,那么你应该没问题。

        如果您手动更新样式,那么您必须自己在 WM_PAINT 中绘制表单。

        如果您真的有野心,您可以维护并绘制自己的后台缓冲区作为位图。

        
        using System.Windows.Forms;
        
        public class MyDisplay : Panel
        {
            public MyDisplay()
            {
                this.DoubleBuffered = true;
        
                // or
        
                SetStyle(ControlStyles.AllPaintingInWmPaint, true);
                SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
                UpdateStyles();
            }
        }
        

        【讨论】:

        • 感谢您发布答案。
        猜你喜欢
        • 2011-11-26
        • 2011-01-05
        • 1970-01-01
        • 2013-10-20
        • 2013-03-05
        • 1970-01-01
        • 1970-01-01
        • 2013-08-14
        • 1970-01-01
        相关资源
        最近更新 更多