VB.NET实现鼠标移动在图片上划线时前一条线消失问题求助
问题根源
你当前的代码仅存储了单条正在绘制的线段的起点st和终点en,每次调用PictureBox1.Invalidate()触发控件重绘时,Paint事件只会绘制最新的这一条线段,此前绘制的内容没有被持久化存储,因此会被清空。
方案1:存储所有历史线段,重绘时全部绘制
该方案灵活度高,后续如果需要支持删除、修改已有线段的需求可以直接扩展。
修改步骤:
- 新增线段存储结构和全局存储列表
- 鼠标抬起时将绘制完成的线段存入列表
Paint事件中遍历所有历史线段逐一绘制
完整修改后代码:
Dim st, en As New Point Dim p As Pen Private mouseButtonPressed As Boolean = False ' 新增线段结构 Public Structure DrawLine Public StartPoint As Point Public EndPoint As Point Sub New(s As Point, e As Point) StartPoint = s EndPoint = e End Sub End Structure ' 存储所有已完成绘制的线段 Dim lineList As New List(Of DrawLine) Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint p = New Pen(Color.Black, 2) Dim g As Graphics = e.Graphics ' 先绘制所有历史线段 For Each l In lineList g.DrawLine(p, l.StartPoint, l.EndPoint) Next ' 再绘制当前正在拖动的线段(预览效果) If mouseButtonPressed Then g.DrawLine(p, st, en) End If End Sub Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp mouseButtonPressed = False ' 绘制完成,将当前线段加入历史列表 lineList.Add(New DrawLine(st, en)) End Sub Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove If mouseButtonPressed Then en = e.Location PictureBox1.Invalidate() End If End Sub Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown If e.Button = MouseButtons.Left Then st = New Point(e.X, e.Y) mouseButtonPressed = True End If End Sub
方案2:直接绘制到PictureBox的Image对象
该方案性能更优,适合不需要二次编辑已画线条的场景,绘制完成的内容会直接固化到图片上,不需要每次重绘所有历史线条。
修改步骤:
- 初始化时为PictureBox绑定一个和控件尺寸一致的空白Bitmap作为绘制载体
- 鼠标抬起时将完成的线段直接绘制到Bitmap上
Paint事件仅需要绘制当前正在拖动的预览线段即可
完整修改后代码:
Dim st, en As New Point Dim p As Pen Private mouseButtonPressed As Boolean = False ' 初始化绑定绘制用的Bitmap Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim bmp As New Bitmap(PictureBox1.Width, PictureBox1.Height) Using g As Graphics = Graphics.FromImage(bmp) g.Clear(Color.White) ' 可替换为你需要的背景色 End Using PictureBox1.Image = bmp End Sub Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint p = New Pen(Color.Black, 2) ' 仅绘制当前拖动的预览线段 If mouseButtonPressed Then e.Graphics.DrawLine(p, st, en) End If End Sub Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp mouseButtonPressed = False ' 将完成的线段直接绘制到Image上固化 Using g As Graphics = Graphics.FromImage(PictureBox1.Image) g.DrawLine(New Pen(Color.Black, 2), st, en) End Using PictureBox1.Invalidate() End Sub Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove If mouseButtonPressed Then en = e.Location PictureBox1.Invalidate() End If End Sub Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown If e.Button = MouseButtons.Left Then st = New Point(e.X, e.Y) mouseButtonPressed = True End If End Sub
内容的提问来源于stack exchange,提问作者user17485293
相关产品推荐
相关产品推荐

