在面板C#上绘制大量图像仍然缓慢且闪烁

在面板C#上绘制大量图像仍然缓慢且闪烁,c#,doublebuffered,onpaint,C#,Doublebuffered,Onpaint,我正在尝试创建一个程序,能够分析DNA数据,并可视化与参考DNA序列的差异。这涉及到大量的字母,我希望在面板上绘制,每个基(a、C、G、T)具有不同的背景色。所以水平线代表一条DNA线 到目前为止,我将此作为一个测试: 创建位图 Bitmap bit; public Form1() { InitializeComponent(); bit = new Bitmap(15, 15); Graphics g = Graphi

我正在尝试创建一个程序,能够分析DNA数据,并可视化与参考DNA序列的差异。这涉及到大量的字母,我希望在面板上绘制,每个基(a、C、G、T)具有不同的背景色。所以水平线代表一条DNA线

到目前为止,我将此作为一个测试:

创建位图

    Bitmap bit;

    public Form1()
    {
        InitializeComponent();

        bit = new Bitmap(15, 15);
        Graphics g = Graphics.FromImage(bit);
        g.FillRectangle(new SolidBrush(Color.Red), new Rectangle(1, 1, 13, 13));
        g.Dispose();
    }
这是我正在绘制的面板的Onpaint处理程序:

    private void p_Paint(object sender, PaintEventArgs e)
    {
        int x_Start = e.ClipRectangle.X;
        int x_Length = e.ClipRectangle.Width;
        int y_Start = e.ClipRectangle.Y;
        int y_Length = e.ClipRectangle.Height;

        Bitmap insb = new Bitmap(RoundUp(x_Length), RoundUp(y_Length));
        Panel p = (Panel)sender;

        Graphics g = p.CreateGraphics();
        Graphics bmp = Graphics.FromImage(insb);

        for (int y = 0; y < insb.Height; y += 15)
        {
            for (int x = 0; x < insb.Width; x += 15)
            {
                bmp.DrawImage(bit, x, y);
            }
        }
        g.DrawImage(insb, x_Start, y_Start);
        bmp.Dispose();
        g.Dispose();
   }

这有了一点改善,但离我想要的还很远。我做错了什么?(这也是我的第一篇帖子,所以请温柔一点;)

找到了答案:整个双缓冲系统都不工作。最后,我在表单加载中添加了以下内容:

System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control).GetProperty(
"DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
aProp.SetValue(canvas, true, null);
我把这个添加到我的表单构造函数中

this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
this.UpdateStyles();

在这张画布上我画了所有的东西。。。谢谢你的帮助

您是否将
表单的
双缓冲
设置为
?没有必要在小组中进行反思。这甚至可能意味着它被忽略了——不确定。您只需设置窗体的属性即可。不要使用
p.CreateGraphics()
。从
PaintEventArgs e
中获取图形,以后不要再处理它。如果它只是具有改变背景颜色的字母,它们实际上不必是图像。使用CreateGraphics()进行绘制在99.9%的情况下是错误的。特别是当您使用双缓冲时,无论您绘制什么,都会在后台缓冲区快速显示到屏幕时再次被擦除。看起来像闪烁一样,激烈的那种。您必须在绘制事件处理程序中使用e.Graphics,以便将图形绘制到后缓冲区而不是屏幕中。使用InvokeMember()是一种技巧,只需从Panel派生您自己的类即可。您还需要在构造函数中将ResizeRedraw属性设置为true,否则调整大小看起来会很糟糕。为您提供32bppPArgb像素格式的位图,x10 fasterI已经完成了您建议的一切@HansPassant,但它仍然闪烁。。。我在Panel类上创建了一个自定义扩展,并将doublebuffered属性设置为true。我已将所有位图更改为正确的像素格式。我现在有了e.Graphics.DrawImage而不是p.DrawImage,所以我应该没事了。。。还有其他关于我做错了什么的想法吗?或者我应该一起走另一条路?无论如何,谢谢你的帮助!
this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
this.UpdateStyles();