Flimmerfreies Zeichnen von Linien in einer Picturebox

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von eugen_v.

    Flimmerfreies Zeichnen von Linien in einer Picturebox

    Hallo alle zusammen,

    ich habe folgendes Problem:
    und zwar möchte ich in eine bestehende PictureBox (hier picFloor) das bereits ein Bild enthält eine Linie zeichnen und diese dann mit der Zeit versezen. Das Problem hierbei ist dass es zwischendurch flimmert.

    VB.NET-Quellcode

    1. Public Sub New()
    2. MyBase.New()
    3. ' Dieser Aufruf ist für den Windows Form-Designer erforderlich.
    4. InitializeComponent()
    5. Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
    6. Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    7. Me.SetStyle(ControlStyles.ResizeRedraw, True)
    8. End Sub
    9. Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    10. MyBase.OnPaint(e)
    11. paintZeroPositionCross()
    12. End Sub
    13. Dim i As Integer = 0
    14. Private Sub paintZeroPositionCross()
    15. Dim g As Graphics
    16. g = Graphics.FromHwnd(picFloor.Handle)
    17. If picFloor.Image IsNot Nothing Then
    18. Dim myPen As New Pen(Color.Red, 3)
    19. Timer1.Enabled = True
    20. Dim imgHeight As Integer = picFloor.Height
    21. Dim imgWidth As Integer = picFloor.Width
    22. picFloor.Refresh()
    23. g.DrawLine(myPen, CInt(imgWidth / 2 + 100), CInt(imgHeight / 2 + i), CInt(imgWidth / 2 - 100), CInt(imgHeight / 2))
    24. i = i + 1
    25. End If
    26. End Sub
    27. Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    28. Me.Invalidate()
    29. End Sub


    hat irgendwer Ideen wie man das Flimmern vermeiden könnte?
    In dem Beispiel wurda in das Image selbst reingezeichnet. Ich muss aber das Image nur als Hintergrund nutzen und in der PictureBox auf dem Image zeichen.
    Ich bin der Meinung dass das Blinken durch

    VB.NET-Quellcode

    1. picFloor.Refresh()
    verursacht wird.
    Kann man eventuell etwas transparentes über die Picturebox ziehen was genau die Selbe Position und Größe hat?
    So müsste man schon mal das Image nicht refreshen und könnte noch

    VB.NET-Quellcode

    1. Me.SetStyle(ControlStyles.DoubleBuffer, True)
    2. Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    benutzen, was das Linienzeichen flimmerfrei machen soll. :)
    Hat einer einen Vorschlag was ich für das "Drüberziehen" nehmen könnte?
    Das Ergebnis ist leider das Selbe. Da ich immer noch

    VB.NET-Quellcode

    1. picFloor.Refresh()
    ausführen muss, damit die alten linien verschwinden, sonst bleiben diese beim Neuzeichnen bestehen.
    Dadurch muss das "große" Hintergrundibld immer wieder neugeladen werden, was meiner Vermutung nach das Blinken zur Folge hat.

    Man muss eine Lösung finden, bei der das hintergrundbild nicht neugezeichnet werden muss
    Refresh is doof.
    Um das Control neu zu zeichnen nimmst du PictureBoxXYZ.Invalidate()
    Die alten Linien verschwinden, indem du vor dem Neuzeichnen der Linie auf das Bitmap dieses mit BMP = New BMP(x,y) neu erzeugst.

    Andere Möglichkeit:
    Bild mit der Linie 1x erzeugen und im Paint den Einfügepunkt des Bitmap verschieben. (e.graphics.drawImage(i,0)). Nach dem Errechnen deiner Verschiebung dann einfach PB.Invalidate().

    Edita:
    Me.SetStyle(ControlStyles.DoubleBuffer, True) funzt nur, wenn du auf die Form zeichnest. Dann müsstest du das Paint der Form nutzen. Bin jetz auf die Schnelle nich sicher, ob dann die PB übermalt wird, oder die PB das Bitmap überdeckt.
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    OptimizedDoubleBuffer, AllPaintingInWMIPaint und UserPaint stell ich dafür immer auf True(mit Setstyle)...
    Setstyle funktioniert vom Prinzip her nur beim Formular, um dies bei einem sonstigen Control zu machen, musst du ein neuest Control erstellen(evtl. ein geerbtes Control, andernfalls mit Reflection->geerbtes Control ist besser..:P)

    durch Invalidate wird allgemein das alte übermalt und neu gezeichn et...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Danke die letzte vorgeschlagene Möglichkeit habe ich auch ausprobiert. Flimmerte noch mehr :(

    Habe jetzt über die eine Picturebox eine andere gelegt

    VB.NET-Quellcode

    1. pbNew = New PictureBox
    2. pbNew.BackColor = Color.Transparent
    3. picFloor.Controls.Add(pbNew)


    Dann male ich die Linien wie vorgeschlagen in ein zweites Bitmap und weise es der pcNew zu.
    Diese funktion habe ich dann in die OnPaint methode eingefügt

    VB.NET-Quellcode

    1. Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    2. MyBase.OnPaint(e)
    3. PaintMyLines()
    4. End Sub
    5. 'Damit kann OnPaint aufgerufen werden
    6. Me.Invalidate()


    Funktioniert super.
    Danke an euch alle.