仅更新图形的一部分

时间:2015-07-26 13:16:56

标签: vb.net graphics refresh

我想知道,有没有简单的方法只更新部分图形?在下面的例子中,我画了1560个小方块,每个10x10px,并涂上了蓝色的3个。这需要相当长的时间(大约1秒),人们可以看到它们在屏幕上的绘制方式。在下一步中,我想将3个蓝色方块移动到不同的位置,这意味着我想保留所有绘制的图形,但是仅将3个方块涂成灰色并将另外3个方块涂成蓝色。 如果我完全重新绘制图片,则需要大量的时间。 1秒上文提到的。我想每秒至少达到几帧,因为我正在做一个小的“动画”模拟。这意味着,代码不必具有性感,但足够简单,可以在非常短暂的程序中使用。

Pattern of squares

在Button4_click代码中勾画的方法很快,但仅仅因为新的方块,擦除旧图形。

请注意,由于性能原因(避免使用一些不必要的事件处理程序和刷新),我将绘制到Panel1而不是PictureBox1上。

草绘测试代码:

Private drawPattern As Boolean = False
Private drawBlueRects As Boolean = False
Dim blueBrush As New SolidBrush(Color.Blue)
Dim grayBrush As New SolidBrush(Color.Gray)

Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint
    Dim g As Graphics = e.Graphics
    If drawPattern Then
        Dim StartY As Integer = 250 - 60 ' just set Y for upper set of squares
        For ir = 1 To 6                  ' paint upper set of squares
            For ic = 0 To 120
                g.DrawRectangle(New Pen(Color.Gray), 5 + ic * 10, StartY + ir * 10, 8, 8)
            Next
        Next ir
        StartY = 250 + 10  ' just set Y for bottom set of squares
        For ir = 1 To 6    ' paint bottom set of squares
            For ic = 0 To 120
                g.DrawRectangle(New Pen(Color.Gray), 5 + ic * 10, StartY + ir * 10, 8, 8)
            Next
        Next ir
        For ic = 0 To 120  ' paint middle set of squares
            g.FillRectangle(grayBrush, 5 + ic * 10, 250 + 10, 8, 8)
        Next
        ' paint 3 blue squares
        g.FillRectangle(blueBrush, 155, 250 + 10, 8, 8)
        g.FillRectangle(blueBrush, 165, 250 + 10, 8, 8)
        g.FillRectangle(blueBrush, 175, 250 + 10, 8, 8)
    ElseIf drawBlueRects = True Then
        ' paint 3 blue squares
        g.FillRectangle(blueBrush, 255, 250 + 10, 8, 8)
        g.FillRectangle(blueBrush, 265, 250 + 10, 8, 8)
        g.FillRectangle(blueBrush, 275, 250 + 10, 8, 8)
    End If
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    drawPattern = True
    Panel1.Refresh()
    'Panel1.Refresh()
End Sub

Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
    drawPattern = False
    drawBlueRects = True
    Panel1.Refresh()
End Sub

我道歉,如果我误解了一个现成的解决方案;请提供这种情况下的链接。

此致

Libor的

2 个答案:

答案 0 :(得分:0)

控件的Invalidate方法指定需要重新绘制控件的特定区域,并且Update方法启动重绘。 Refresh方法只调用没有参数的Invalidate,表示整个控件需要重新绘制,然后调用Update。而不是Refresh,而是自己致电InvalidateUpdate。这样,您可以将适当的参数传递给Invalidate,以准确指定要重绘的控件的哪个部分或哪些部分。您可以针对复杂区域多次致电Invalidate

答案 1 :(得分:0)

我通过一种解决方法解决了这个问题 - 我每次更改时都会绘制一个位图并使用此位图更新PictureBox。由于我可以绘制到位图的特定位置,因此重绘不会出现问题:

在类标题中定义位图:

Dim bm As New Bitmap(1910, 500)

初步绘图:

Private Sub CreateImage()
    Dim w As Integer = bm.Width ' or PictureBox1.Width
    Dim h As Integer = bm.Height  ' or PictureBox1.Height
    Dim bmp As New Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
    bm = bmp
    Using g As Graphics = Graphics.FromImage(bmp)  ' get it from current state of bitmap
        Me.DoubleBuffered = True
        Dim Ypos As Integer = 0
        Call DrawRecArray(StartY - 100, g, NoOfBaysInSet)
        Call DrawRecArray(StartY + 10, g, NoOfBaysInSet)
        For ic = 0 To icLimit   ' paint middle set of squares
            g.FillRectangle(grayBrush, 5 + ic * 10, StartY + 10, 8, 8)
            Call DrawStringFunc(5 + ic * 10, StartY - 70 + Ypos * 5, ic + 1, g, drawFont)
            Ypos += 1
            If Ypos = 3 Then Ypos = 0
            If Ypos = 1 Then Call DrawStringFunc(5 + ic * 10, StartY - 90 + Ypos * 5, (ic + 1 * 3) / 3, g, drawFontB)
        Next
    End Using
    PictureBox1.Image = bmp  ' put the bitmap into Picturebox !!!
End Sub

更新位图:

Private Sub UpdateImage(FromPos As Int16, ToPos As Int16)
    Dim w As Integer = bm.Width
    Dim h As Integer = bm.Height
    Dim bmp As New Bitmap(Me.PictureBox1.Image) ' now get the bitmap from the PictureBox
    bm = bmp
    Using g As Graphics = Graphics.FromImage(bmp)
        Me.DoubleBuffered = True
        g.FillRectangle(backBrush, 5 + FromPos * 10, StartY + 10, 28, 8)
        g.FillRectangle(grayBrush, 5 + FromPos * 10, StartY + 10, 8, 8)
        g.FillRectangle(grayBrush, 15 + FromPos * 10, StartY + 10, 8, 8)
        g.FillRectangle(grayBrush, 25 + FromPos * 10, StartY + 10, 8, 8)
        g.FillRectangle(blueBrush, 5 + ToPos * 10, StartY + 10, 28, 8)
    End Using
    PictureBox1.Image = bmp  ' update pictureBox with modified bitmap
End Sub

我相信这是一个有价值的答案。我与GDI打交道已经有好几年了,并且反复碰到这个问题,并且在成千上万的答案中,只有少数人描述了没有_paint事件的重绘,我认为这对于这种情况是无用的。大多数样本都是一次性的图纸。

此致

Libor的