Auf ein Backroundimage in einer Picturebox zeichnen ohne Performance verlust

  • VB.NET

Es gibt 30 Antworten in diesem Thema. Der letzte Beitrag () ist von ThePlexian.

    Auf ein Backroundimage in einer Picturebox zeichnen ohne Performance verlust

    Hallo,

    ich habe ein Problem:
    Ich habe ein Control, indem eine Picturebox in dem ein Hintergrundbild zur Laufzeit geladen wird.
    Außerdem kann ich auf diese Picturebox mit dem Hintergrundbild zeichnen.

    Nun ist das Problem, dass ich beim zeichnen einen Performance verlust habe.
    Das bedeutet, wenn ich zeichne, sind die Linien nicht mehr so "rund" wie vorher, sondern eckiger.
    Außerdem wird etwas langsamer gezeichnet.

    Hat dafür jemand eine Lösung ?

    Danke

    vivil schrieb:

    wenn ich zeichne
    Mit welchem Code?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub pbNew_MouseDown(sender As Object, e As MouseEventArgs) Handles pbNew.MouseDown
    2. If e.Button = MouseButtons.Left Then ' draw a filled circle if left mouse is down
    3. If mousePath Is Nothing Then
    4. mousePath = New System.Drawing.Drawing2D.GraphicsPath()
    5. End If
    6. speichern = True
    7. mousePath.StartFigure() ' The L mouse is down so we need to start a new line in mousePath
    8. 'End If
    9. End If
    10. End Sub
    11. Private Sub pbNew_MouseMove(sender As Object, e As MouseEventArgs) Handles pbNew.MouseMove
    12. If e.Button = MouseButtons.Left Then ' draw a filled circle if left mouse is down
    13. If mousePath Is Nothing Then
    14. mousePath = New System.Drawing.Drawing2D.GraphicsPath()
    15. End If
    16. Try
    17. mousePath.AddLine(e.X, e.Y, e.X, e.Y) 'Add mouse coordiantes to mousePath
    18. Catch
    19. MsgBox("No way, Hose!")
    20. End Try
    21. 'End If
    22. pnlGrundriss.Invalidate() 'Repaint the PictureBox using the PictureBox1 Paint event
    23. End If
    24. End Sub
    25. Private Sub pbNew_Paint(sender As Object, e As PaintEventArgs) Handles pbNew.Paint
    26. Try
    27. myUserColor = (System.Drawing.Color.Black) 'You can remove this line and add a user selected color to
    28. 'change the value of myUserColor
    29. e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
    30. e.Graphics.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
    31. e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
    32. myAlpha = 255 ' This will give the color a Alpha effect, you can set this to 255 if you want a full color
    33. Dim CurrentPen = New Pen(Color.FromArgb(myAlpha, myUserColor), myPenWidth) 'Set up the pen
    34. e.Graphics.DrawPath(CurrentPen, mousePath) 'draw the path! :)
    35. 'End If
    36. '*********************** NOTE ***********************************************
    37. 'The line below set the pen up with the ability to add user selected Alpha, Color and Penwidth
    38. ' A simpler, but less flexible solution would be to replace the line with the following code:
    39. 'Dim CurrentPen = New Pen(System.Drawing.Color.Black, myPenWidth)
    40. '************ End Note ***************************
    41. Catch
    42. ' MsgBox("Not happening!")
    43. End Try
    44. End Sub


    @vivil so was:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private PointStart As Point
    3. Private PointEnd As Point
    4. Private draw As Boolean = False
    5. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown
    6. PointStart = e.Location
    7. PointEnd = e.Location
    8. draw = True
    9. Me.Invalidate()
    10. End Sub
    11. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles MyBase.MouseMove
    12. PointEnd = e.Location
    13. Me.Invalidate()
    14. End Sub
    15. Private Sub Form1_MouseUp(sender As Object, e As MouseEventArgs) Handles MyBase.MouseUp
    16. draw = False
    17. End Sub
    18. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
    19. If draw Then
    20. e.Graphics.DrawLine(Pens.Black, PointStart, PointEnd)
    21. End If
    22. End Sub
    23. End Class

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Danke für deine Antwort.
    Nur leider ist es nicht das was ich möchte.
    Ich möchte Wenn ich die linke Maustaste gedrückt halte, die Linie direkt zeichnen.
    Das funktioniert bei meinem Code ja auch schon alles.
    Das Problem ist nur, dass das Hintergrundbild der Picturebox das zeichnen verlangsamt.
    Definiere

    vivil schrieb:

    die Linie direkt zeichnen.
    oder poste mal ein Bild von deinem Output.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Das MouseMove-Event fügt ja eine Linie hinzu, diese wird dann ja durch Invalidate direkt in dem Paint-Event gezeichnet.
    Das bedeutet also, sobald man die linke Maustaste drückt, diese gedrückt hält und die Maus verschiebt, wird eine Linie gezeichnet.
    Gibt es eine Möglichkeit, 2 Pictureboxen im Deisgner übereinander zu legen, in die eine Picturebox das Bild zu laden und auf der anderen zu zeichnen ?
    Mein Problem dabei ist, dass entweder nur gezeichnet werden kann, oder nur das Bild da ist.
    @vivil So was:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private PointStart As Point
    3. Private PointEnd As Point
    4. Private draw As Boolean = False
    5. Private AllLines As New List(Of Linie)
    6. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown
    7. PointStart = e.Location
    8. PointEnd = e.Location
    9. draw = True
    10. Me.Invalidate()
    11. End Sub
    12. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles MyBase.MouseMove
    13. PointEnd = e.Location
    14. Me.Invalidate()
    15. End Sub
    16. Private Sub Form1_MouseUp(sender As Object, e As MouseEventArgs) Handles MyBase.MouseUp
    17. draw = False
    18. AllLines.Add(New Linie(PointStart, PointEnd))
    19. End Sub
    20. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
    21. If draw Then
    22. e.Graphics.DrawLine(Pens.Black, PointStart, PointEnd)
    23. End If
    24. For Each line In AllLines
    25. line.DrawLine(e.Graphics)
    26. Next
    27. End Sub
    28. End Class
    29. Class Linie
    30. Private PointStart As Point
    31. Private PointEnd As Point
    32. Public Sub DrawLine(g As Graphics)
    33. g.DrawLine(Pens.Black, PointStart, PointEnd)
    34. End Sub
    35. Public Sub New(start As Point, ende As Point)
    36. PointStart = start
    37. PointEnd = ende
    38. End Sub
    39. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ah okay, verstehe.
    Dies ist aber nicht die Lösung die ich suche, sorry.
    Es dürfen keine Linien sein, sondern es muss ein GraphicsPath sein, weil dann können auch kurven gezeichnet werden.
    Also sobald die linke Maustaste gedrückt wird und man die Maus bewegt, genau die Bewegung der Maus gezeichnet wird.
    Das funktioniert ja auch alles, nur sobald ein Bild in der Picturebox ist, verliert das zeichnen an Performance, heißt also,
    dass das zeichnen zu langsam ist.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „vivil“ ()

    vivil schrieb:

    Es dürfen keine Linien sein
    Dann merk Dir bei MouseMove jeden Punkt und bearbeite die Klasse entsprechend.
    Dies als Anhaltspunkt:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private draw As Boolean = False
    3. Private AllLines As New List(Of Linie)
    4. Private actLine As Linie
    5. Private col() As Color = {Color.Red, Color.Green, Color.Blue}
    6. Private index As Integer = 0
    7. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown
    8. actLine = New Linie(e.Location, col(index))
    9. index = (index + 1) Mod col.Length
    10. draw = True
    11. Me.Invalidate()
    12. End Sub
    13. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles MyBase.MouseMove
    14. If draw Then
    15. actLine.Add(e.Location)
    16. Me.Invalidate()
    17. End If
    18. End Sub
    19. Private Sub Form1_MouseUp(sender As Object, e As MouseEventArgs) Handles MyBase.MouseUp
    20. If draw Then
    21. actLine.Add(e.Location)
    22. AllLines.Add(actLine)
    23. Me.Invalidate()
    24. actLine = Nothing
    25. End If
    26. draw = False
    27. End Sub
    28. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
    29. If draw AndAlso actLine.allPoints.Count > 1 Then
    30. e.Graphics.DrawLines(Pens.Black, actLine.allPoints.ToArray)
    31. End If
    32. For Each line In AllLines
    33. line.DrawLine(e.Graphics)
    34. Next
    35. End Sub
    36. End Class
    37. Class Linie
    38. Public allPoints As New List(Of Point)
    39. Private col As Color
    40. Public Sub DrawLine(g As Graphics)
    41. g.DrawPolygon(New Pen(col), allPoints.ToArray)
    42. End Sub
    43. Public Sub New(pt As Point, co As Color)
    44. col = co
    45. allPoints.Add(pt)
    46. End Sub
    47. Public Sub Add(pt As Point)
    48. allPoints.Add(pt)
    49. End Sub
    50. End Class

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!



    So sieht es aus, wenn ich schneller zeichne, aber wie bekomme ich es hin, dass die Zeichnung so aussieht wie oben ?


    Bei OneNote z.B. kann man ein Bild in den Hintergrund laden und die gezeichneten Linien werden wie im obigen Bild dargestellt, egal wie schnell man zeichnet.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „vivil“ ()

    vivil schrieb:

    egal wie schnell man zeichnet
    AHa.
    Da setzt Du aber die Punkte einzeln.
    Aus den Punkten werden Splines gemacht, so etwa:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private AllLines As New List(Of Linie)
    3. Private actLine As New Linie
    4. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown
    5. actLine.Add(e.Location)
    6. Me.Invalidate()
    7. End Sub
    8. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
    9. If actLine.allPoints.Count > 1 Then
    10. e.Graphics.DrawLines(Pens.Black, actLine.allPoints.ToArray)
    11. End If
    12. For Each line In AllLines
    13. line.DrawLine(e.Graphics)
    14. Next
    15. End Sub
    16. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    17. AllLines.Add(actLine)
    18. actLine = New Linie
    19. Me.Invalidate()
    20. End Sub
    21. End Class
    22. Class Linie
    23. Public allPoints As New List(Of Point)
    24. Private allPointsIntern As New List(Of Point)
    25. Public Sub DrawLine(g As Graphics)
    26. If allPointsIntern.Count >= 4 Then
    27. g.DrawBeziers(Pens.Black, allPointsIntern.ToArray)
    28. End If
    29. End Sub
    30. Public Sub Add(pt As Point)
    31. allPoints.Add(pt)
    32. If (allPoints.Count - 1) Mod 3 = 0 Then
    33. allPointsIntern.Clear()
    34. allPointsIntern.AddRange(allPoints)
    35. End If
    36. End Sub
    37. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wie kommen die Punkte in Deinen

    vivil schrieb:

    GraphicsPath
    :?:
    (ohne jetzt Deinen Code verstehen zu müssen)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Neuen Path zeichnen(MouseDown):

    VB.NET-Quellcode

    1. mousePath.StartFigure() ' The L mouse is down so we need to start a new line in mousePath


    Dort werden die Punkte in meinen GraphicsPath geschrieben (MouseMove):

    VB.NET-Quellcode

    1. mousePath.AddLine(e.X, e.Y, e.X, e.Y) 'Add mouse coordiantes to mousePath


    Path zeichnen(Paint):

    VB.NET-Quellcode

    1. e.Graphics.DrawPath(CurrentPen, mousePath) 'draw the path! :)

    vivil schrieb:

    VB.NET-Quellcode

    1. mousePath.AddLine(e.X, e.Y, e.X, e.Y)
    heißt, dass Deine Linien jeweils nur aus einem Punkt bestehen.
    Da kannst Du Dir auch gleich nur die Punkte merken und ein Polygon malen, ohne GraphicsPath.
    Oder hat es mit diesem eine besondere Bewandtnis?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    vivil schrieb:

    wo die Maus hin und her bewegt wurde.
    Dann merk Dir die Punkte und mach DrawLines() oder DrawBeziers(), letztere mit Auflagen, siehe mein Beispiel.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    vivil schrieb:

    nicht mehr mit GraphicsPath arbeiten
    Jou.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!