[英]C# paint program flickering
I'm trying to make a simple paint program in C#, but it keeps flickering when I'm drawing, like I need some kind of double buffering, but I don't know how to do it. 我正在尝试用C#制作一个简单的绘图程序,但是当我绘图时它会一直闪烁,就像我需要某种双缓冲一样,但我不知道该怎么做。
I am drawing on a Panel
and I'm using a Bitmap
to store the graphics. 我正在绘制一个
Panel
,我正在使用Bitmap
来存储图形。
Here's my code: 这是我的代码:
public partial class Form1 : Form
{
private Bitmap drawing;
private bool leftDown = false;
private int prevX;
private int prevY;
private int currentX;
private int currentY;
public Form1()
{
InitializeComponent();
drawing = new Bitmap(panel1.Width, panel1.Height);
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
leftDown = true;
prevX = e.X;
prevY = e.Y;
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (leftDown)
{
Graphics g = Graphics.FromImage(drawing);
currentX = e.X;
currentY = e.Y;
g.DrawLine(new Pen(Color.Black), new Point(currentX, currentY), new Point(prevX, prevY));
panel1.Invalidate();
prevX = currentX;
prevY = currentY;
g.Dispose();
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
leftDown = false;
}
private void panel1_MouseLeave(object sender, EventArgs e)
{
leftDown = false;
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImageUnscaled(drawing, 0, 0);
}
}
You not only should turn DoubleBuffered
to true
, but also use PictureBox
instead of Panel
and draw on it. 您不仅应该将
DoubleBuffered
转为true
,还要使用PictureBox
而不是Panel
并在其上绘制。 This should solve your issue :). 这应该解决你的问题:)。
You need to subclass Panel to do this, because you need to override certain things. 您需要子类化Panel才能执行此操作,因为您需要覆盖某些内容。 A
Panel
like this should work: 像这样的
Panel
应该工作:
class DoubleBufferedPanel : Panel {
public DoubleBufferedPanel() : base() {
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.DoubleBuffered |
ControlStyles.Opaque |
ControlStyles.OptimizedDoubleBuffer, true);
}
public override void OnPaint(PaintEventArgs e) {
// Do your painting *here* instead, and don't call the base method.
}
// Override OnMouseMove, etc. here as well.
}
However, you don't need the functionality Panel
adds to Control
at all, that is for it to be functioning as a container. 但是,您根本不需要
Panel
添加到Control
的功能,即它可以作为容器运行。 So, in fact, you should be inheriting from Control
unless you need subcontrols. 所以,事实上,除非你需要子
Control
否则你应该从Control
继承。
Another improvement might be to only Invalidate
with the Rectangle
that changed. 另一个改进可能是仅对已更改的
Rectangle
进行Invalidate
。 This will repaint one area and reduce drawing time. 这将重绘一个区域并缩短绘图时间。 You can also pass a
srcRect
to Graphics.DrawImage
, that srcRect
being calculated from e.ClipRectangle
, for even better performance if subclassing Panel
doesn't work for you. 您也可以通过一个
srcRect
到Graphics.DrawImage
,即srcRect
是从计算e.ClipRectangle
,甚至更好的性能,如果子类Panel
不会为你工作。
Normally, simply adding this.DoubleBuffered = true;
通常,只需添加
this.DoubleBuffered = true;
in your code should do the trick. 在你的代码中应该做的伎俩。
If it does not, add this code to your form : 如果没有,请将此代码添加到表单中:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
You can also change it using Reflection, but there is no advantage, neither readability or speed. 您也可以使用Reflection更改它,但没有优势,无论是可读性还是速度。
When painting pixel maps in the Paint event, the flickering is often caused by Windows forms because it first draws the background and then the pixel map. 在Paint事件中绘制像素贴图时,闪烁通常是由Windows窗体引起的,因为它首先绘制背景,然后绘制像素贴图。 So the flicker is the background that becomes visible for a fraction of a second.
因此,闪烁是在几分之一秒内变得可见的背景。
You can set the Opaque
style in the panel's ControlStyle
property. 您可以在面板的
ControlStyle
属性中设置Opaque
样式。 That will turn of the background drawing because Windows Forms now assumes that your code will completely draw the contents of the panel. 这将转变背景图,因为Windows窗体现在假定您的代码将完全绘制面板的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.