VB.NET 在不删除先前更改的情况下在 PictureBox 上绘制多条线

VB.NET drawing multiple lines on a PictureBox without removing previous changes

我正在尝试在 VB.NET PictureBox 上绘制多条线而不删除之前的更改。如果我尝试在 e.graphics 的不同时间在 PictureBox 上画两条线,那么它会删除之前的 lines/changes.

我在 PictureBoxpaint 活动中使用此代码。

Public Class DrawLine

Dim point1X As Integer = 10
Dim point1Y As Integer = 10

Dim point2X As Integer = 50
Dim point2Y As Integer = 50

Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    Dim pt As New Point(point1X, point1Y)
    Dim pt1 As New Point(point2X, point2Y)
    e.Graphics.DrawLine(Pens.Green, pt, pt1)    
End Sub

End Class

此示例完美地在 PictureBox.

内绘制了一条绿线

但是,当我有一个按钮在 PictureBox 上绘制另一条线时,在表单已经绘制之后,之前绘制的线消失了。

例如,如果我有这样的函数可以绘制另一条线

Private Function DrawAnotherLine(xPos1 As Integer, yPos1 As Integer, xPos2 As Integer, yPos2 As Integer)

point1X = xPos1
point1Y = yPos1

point2X = xPos2
point2Y = yPos2

PictureBox1.Invalidate()
End Function

删除第一条线,只画第二条线。我希望它在第一行之上绘制第二行,而不只是删除第一行,我该怎么做?

(注意:我不能在函数中包含绘制第一条线,因为此函数将在已绘制的线之上多次使用)。

GDI+绘图非常简单:

  1. 声明一个或多个字段来存储表示您的绘图的数据。
  2. 处理要绘制的控件的 Paint 事件。
  3. 在步骤 2 的事件处理程序中,从步骤 1 中声明的字段中获取数据并执行绘图。
  4. 要更改绘图,请修改在步骤 1 中声明的字段并在控件上调用 Invalidate

如果您希望能够绘制多条线,那么您首先需要一个表示单条线的数据结构,然后在某处存储该数据结构的多个实例。最明显的方法是定义一个 class 或包含单行数据的结构,例如

Public Class Line

    Public ReadOnly Property StartPoint As Point

    Public ReadOnly Property EndPoint As Point

    Public Sub New(startPoint As Point, endPoint As Point)
        Me.StartPoint = startPoint
        Me.EndPoint = endPoint
    End Sub

End Class

然后声明一个引用该类型集合的字段:

Private lines As New List(Of Line)

您的 Paint 事件处理程序然后绘制集合中的所有线条:

Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    For Each line In lines
        e.Graphics.DrawLine(Pens.Black, line.StartPoint, line.EndPoint)
    Next
End Sub

要绘制一条新线,请将新的 Line 对象添加到集合中,并 Invalidate 控件:

Private Sub AddNewLine(startPoint As Point, endPoint As Point)
    lines.Add(New Line(startPoint, endPoint))
    PictureBox1.Invalidate()
End Sub

如何获得这些积分取决于您。您可以在 MouseDown 事件中记录位置,然后在 MouseUp 事件中调用 AddNewLine,或者您可以完全做其他事情。

调用Invalidate时最好指定尽可能小的区域,但这超出了本题的范围。