在面板C#上绘制大量图像仍然缓慢且闪烁
我正在尝试创建一个程序,能够分析DNA数据,并可视化与参考DNA序列的差异。这涉及到大量的字母,我希望在面板上绘制,每个基(a、C、G、T)具有不同的背景色。所以水平线代表一条DNA线 到目前为止,我将此作为一个测试: 创建位图在面板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
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();