C#快速绘图时线条出现间隙问题求助(附代码)
解决图片画笔快速绘图出现间隙的问题
问题根源
你当前的代码仅在每次MouseMove触发时绘制单张图片,但鼠标快速移动时,系统触发MouseMove的间隔会变大,相邻两次绘制的位置距离超过图片尺寸,就会出现间隙。另外用CreateGraphics绘制的内容不会持久化,窗口重绘后绘制的内容会消失,这也是需要修复的问题。
解决方案
核心思路是记录上一次鼠标位置,在两次鼠标位置之间的路径上连续绘制图片,同时把绘制内容缓存到Bitmap中,通过Panel的Paint事件渲染,保证内容持久不丢失。
修改后的完整代码:
using System; using System.Drawing; using System.Windows.Forms; namespace drawing_using_image { public partial class Form1 : Form { private Image _brushImage; private Bitmap _canvasBitmap; private Point _lastMousePos = Point.Empty; private int _brushSize = 45; // 和你设置的图片尺寸保持一致 public Form1() { InitializeComponent(); _brushImage = Properties.Resources.angle45; // 初始化画布Bitmap,尺寸和Panel一致 _canvasBitmap = new Bitmap(panel1.Width, panel1.Height); // 绑定Panel的Paint事件,用于渲染缓存画布 panel1.Paint += Panel1_Paint; // 监听Panel尺寸变化,重新初始化画布 panel1.Resize += (s, e) => { _canvasBitmap?.Dispose(); _canvasBitmap = new Bitmap(panel1.Width, panel1.Height); panel1.Invalidate(); }; } private void Panel1_Paint(object sender, PaintEventArgs e) { // 将缓存的画布内容绘制到Panel上 e.Graphics.DrawImage(_canvasBitmap, Point.Empty); } private void panel1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { // 鼠标按下时记录初始位置 _lastMousePos = e.Location; // 在初始位置绘制一次画笔 DrawBrushAtPosition(e.Location); } } private void panel1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left && _lastMousePos != Point.Empty) { Point currentPos = e.Location; // 计算两次鼠标位置的直线距离 double distance = Math.Sqrt(Math.Pow(currentPos.X - _lastMousePos.X, 2) + Math.Pow(currentPos.Y - _lastMousePos.Y, 2)); if (distance > 0) { // 计算每步的移动增量(取画笔尺寸的一半作为步长,确保无间隙) float stepX = (currentPos.X - _lastMousePos.X) / (float)distance * (_brushSize / 2f); float stepY = (currentPos.Y - _lastMousePos.Y) / (float)distance * (_brushSize / 2f); float currentX = _lastMousePos.X; float currentY = _lastMousePos.Y; // 沿着路径循环绘制,直到接近当前鼠标位置 while (Math.Sqrt(Math.Pow(currentX - currentPos.X, 2) + Math.Pow(currentY - currentPos.Y, 2)) > _brushSize / 2f) { DrawBrushAtPosition(new Point((int)currentX, (int)currentY)); currentX += stepX; currentY += stepY; } } // 在当前鼠标位置补画一次 DrawBrushAtPosition(currentPos); // 更新上一次鼠标位置 _lastMousePos = currentPos; } } private void panel1_MouseUp(object sender, MouseEventArgs e) { // 鼠标松开时重置上一次位置,避免误绘制 _lastMousePos = Point.Empty; } private void DrawBrushAtPosition(Point pos) { // 在缓存画布上绘制图片,以鼠标点为中心 using (Graphics g = Graphics.FromImage(_canvasBitmap)) { Rectangle rect = new Rectangle(pos.X - _brushSize/2, pos.Y - _brushSize/2, _brushSize, _brushSize); g.DrawImage(_brushImage, rect); } // 通知Panel重绘,更新显示内容 panel1.Invalidate(); } } }
关键修改说明
- 新增
_canvasBitmap作为绘制缓存,所有绘制操作都在这个Bitmap上进行,解决了CreateGraphics临时绘制的内容丢失问题 - 记录
_lastMousePos,在MouseMove时计算两次位置的路径,按步长连续绘制图片,彻底填补间隙 - 将图片绘制位置调整为以鼠标点为中心,更符合画笔的使用直觉
- 处理Panel的Resize事件,保证画布尺寸始终和Panel一致
- 新增
MouseUp事件,重置上一次位置,避免松开鼠标后出现误绘制
内容的提问来源于stack exchange,提问作者Hassn shalabi
相关产品推荐
相关产品推荐

