我正在开发一种绘图程序,但在绘制橡皮筋线时移动鼠标光标时出现闪烁问题。我希望你能帮我消除那条闪烁的线,这是代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace GraphicsTest
{
public partial class Form1 : Form
{
int xFirst, yFirst;
Bitmap bm = new Bitmap(1000, 1000);
Graphics bmG;
Graphics xG;
Pen pen = new Pen(Color.Black, 1);
bool draw = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bmG = Graphics.FromImage(bm);
xG = this.CreateGraphics();
bmG.Clear(Color.White);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
xFirst = e.X;
yFirst = e.Y;
draw = true;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
bmG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
draw = false;
xG.DrawImage(bm, 0, 0);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (draw)
{
xG.DrawImage(bm, 0, 0);
xG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
xG.DrawImage(bm, 0, 0);
}
}
}
最佳答案
首先不要使用 CreateGraphics()
除非绝对必要。将事件处理程序绑定(bind)到 OnPaint
并在您想要刷新表面时调用 Invalidate()
。
如果您不希望它闪烁,则需要对您的绘图表面进行双重缓冲。最简单的方法是将表单的 DoubleBuffered
属性设置为 True。
如果您打算扩展它以对 PictureBox 控件进行绘图,我强烈推荐您使用它。 PictureBox 默认是双缓冲的,允许您更简单地控制绘图区域。
在代码中:
public partial class Form1 : Form
{
int xFirst, yFirst;
Bitmap bm = new Bitmap(1000, 1000);
Graphics bmG;
Pen pen = new Pen(Color.Black, 1);
bool draw = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bmG = Graphics.FromImage(bm);
bmG.Clear(Color.White);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
xFirst = e.X;
yFirst = e.Y;
draw = true;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
bmG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
draw = false;
Invalidate();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (draw)
{
Invalidate();
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (draw) {
e.Graphics.DrawImage(bm, 0, 0);
e.Graphics.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
} else {
e.Graphics.DrawImage(bm, 0, 0);
}
}
}
编辑:
另一个问题,您正在创建一个私有(private) Pen
成员。笔(和画笔,以及许多 GDI+ 对象)表示需要处理的非托管对象的句柄,否则您的程序将泄漏。要么将它们包装在 using
语句中(首选且异常安全的方式),要么在表单的 Dispose
方法中显式处理它们。
或者,在 System.Drawing 中,您可以访问一些不需要(也不应该)处理的预建钢笔和画笔。像这样使用它们:
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (draw) {
e.Graphics.DrawImage(bm, 0, 0);
e.Graphics.DrawLine(Pens.Black, xFirst, yFirst, e.X, e.Y);
} else {
e.Graphics.DrawImage(bm, 0, 0);
}
}
关于C#图形闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2608909/