Linien sind nach aufruf von Invalidate() Weg

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Linien sind nach aufruf von Invalidate() Weg

    Ich bau mir gerade ein galgenmännchen Spiel zusammen, habe aber das problem, das die gezeichneten Linien wieder verschwinden nachdem ich Invalidate() aufrufe.

    So sieht meine Paint Sub aus:
    Mit fehlversuchen ist gemeint wenn der Spieler einen Falschen Buchstaben gewählt hat, wird Fehlversuche += 1 gemacht.

    Das Problem ist, wenn Fhlversuche = 2 oder Höher ist, dann werden die Vorigen Linien gelöscht und nur eine Der Linien wird neu gezeichnet.

    Frage: Wie bekomme ich es hin, das alle vorherigen Linien auch wieder gezeichnet werden, bzw. gar nicht gelöscht werden.

    VB.NET-Quellcode

    1. Private Sub Galgenbox_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Galgenbox.Paint
    2. Dim g As Graphics = e.Graphics
    3. Dim b As Pen = New Pen(Brushes.Black, 5)
    4. If start Then
    5. Select Case FehlVersuche
    6. Case 1 : g.DrawLine(b, 25, 150, 175, 150) 'Boden
    7. Case 2 : g.DrawLine(b, 75, 150, 75, 25) 'Stammfuß
    8. Case 3 : g.DrawLine(b, 73, 25, 150, 25) 'Balken
    9. Case 4 : g.DrawLine(b, 75, 50, 100, 25) 'Querstütze
    10. Case 5 : g.DrawLine(b, 150, 23, 150, 50) 'Seil
    11. Case 6 : g.DrawEllipse(b, 140, 50, 20, 20) 'Kopf
    12. Case 7 : g.DrawLine(b, 150, 70, 150, 100) 'Rumpf
    13. Case 8 : g.DrawLine(b, 150, 98, 135, 125) 'linkes Bein
    14. Case 9 : g.DrawLine(b, 150, 98, 165, 125) 'rechtes Bein
    15. Case 10 : g.DrawLine(b, 150, 90, 130, 75) 'linker Arm
    16. Case 11 : g.DrawLine(b, 150, 90, 170, 75) 'rechter Arm
    17. End Select
    18. End If
    19. End Sub


    Und das hier ist mein Button der den eingegebenen Buchstaben überprüft:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. If Not TextBox1.Text = "" Then
    3. If Not txt.Contains(TextBox1.Text) Then
    4. FehlVersuche += 1
    5. Galgenbox.Invalidate()
    6. End If
    7. End If
    Hey.

    Dass die Linien gelöscht werden, liegt daran, dass bei jedem Invalidate() der ganze ausgewählte Bereich, welcher ohne Angabe von Parametern der des ganzen Formulars ist, mit der Hintergrundfarbe gecleart wird. Alles, was vorher gezeichnet wurde, muss neugezeichnet werden. Da du je nach Case nur eine Linie zeichnest, ist das, was du letzten Endes am Bildschirm siehst.

    In anderen Sprachen gibt es die Möglichkeit, alle Cases ab einem bestimmten durchzuführen, indem man die Break-Anweisung am Ende weglässt. Anscheinend ist so etwas in VB.NET nicht möglich; zumindest sagt das Google.
    Was du allerdings machen könntest, wäre so etwas:

    VB.NET-Quellcode

    1. Dim max = 11 ' stellt den höchsten Wert, den "FehlVersuche" annehmen kann, dar
    2. Select Case FehlVersuche
    3. Case 1 To max : g.DrawLine(b, 25, 150, 175, 150) 'Boden
    4. Case 2 To max : g.DrawLine(b, 75, 150, 75, 25) 'Stammfuß
    5. Case 3 To max : g.DrawLine(b, 73, 25, 150, 25) 'Balken
    6. Case 4 To max : g.DrawLine(b, 75, 50, 100, 25) 'Querstütze
    7. Case 5 To max : g.DrawLine(b, 150, 23, 150, 50) 'Seil
    8. Case 6 To max : g.DrawEllipse(b, 140, 50, 20, 20) 'Kopf
    9. Case 7 To max : g.DrawLine(b, 150, 70, 150, 100) 'Rumpf
    10. Case 8 To max : g.DrawLine(b, 150, 98, 135, 125) 'linkes Bein
    11. Case 9 To max : g.DrawLine(b, 150, 98, 165, 125) 'rechtes Bein
    12. Case 10 To max : g.DrawLine(b, 150, 90, 130, 75) 'linker Arm
    13. Case 11 To max : g.DrawLine(b, 150, 90, 170, 75) 'rechter Arm
    14. End Select
    Die "max"-Variable muss modifiziert werden, je höher der Wert von "FehlVersuche" werden kann.
    Wie füge ich den die Linien in eine Liste? Das dumme ist, das es auch noch eine Ellipse enthällt (Der Kopf). Dann wie zeichne ich den alle Linien in der Liste aus.
    Habe mal ein Array aus Punkten erstellt. Weis aber nun immer noch nicht weiter...

    VB.NET-Quellcode

    1. Dim p() As Point = {New Point(25, 150), New Point(175, 150),
    2. New Point(75, 150), New Point(75, 25),
    3. New Point(73, 25), New Point(150, 25),
    4. New Point(75, 50), New Point(100, 25),
    5. New Point(150, 23), New Point(150, 50),
    6. New Point(150, 70), New Point(150, 100),
    7. New Point(150, 98), New Point(135, 125),
    8. New Point(150, 98), New Point(165, 125),
    9. New Point(150, 90), New Point(130, 75),
    10. New Point(150, 90), New Point(170, 75)}


    Dort sind alle Punkte der Linien eingetragen, außer die Ellipse
    Da mein letzter Versuch nicht funktioniert hat, hier etwas anderes:

    VB.NET-Quellcode

    1. If FehlVersuche >= 1 Then g.DrawLine(b, 25, 150, 175, 150)
    2. If FehlVersuche >= 2 Then g.DrawLine(...)
    Damit sollte es definitiv funktionieren, da jede If-Anweisung immer ausgeführt wird, egal, ob eine vorherige schon wahr war oder nicht, was bei Select-Case anscheinend nicht der Fall ist.

    haiyyu schrieb:

    Damit sollte es definitiv funktionieren
    Korrekt, habs probierrt:

    VB.NET-Quellcode

    1. If start Then
    2. If FehlVersuche >= 1 Then g.DrawLine(b, 25, 150, 175, 150) 'Boden
    3. If FehlVersuche >= 2 Then g.DrawLine(b, 75, 150, 75, 25) 'Stammfuß
    4. If FehlVersuche >= 3 Then g.DrawLine(b, 73, 25, 150, 25) 'Balken
    5. If FehlVersuche >= 4 Then g.DrawLine(b, 75, 50, 100, 25) 'Querstütze
    6. If FehlVersuche >= 5 Then g.DrawLine(b, 150, 23, 150, 50) 'Seil
    7. If FehlVersuche >= 6 Then g.DrawEllipse(b, 140, 50, 20, 20) 'Kopf
    8. If FehlVersuche >= 7 Then g.DrawLine(b, 150, 70, 150, 100) 'Rumpf
    9. If FehlVersuche >= 8 Then g.DrawLine(b, 150, 98, 135, 125) 'linkes Bein
    10. If FehlVersuche >= 9 Then g.DrawLine(b, 150, 98, 165, 125) 'rechtes Bein
    11. If FehlVersuche >= 10 Then g.DrawLine(b, 150, 90, 130, 75) 'linker Arm
    12. If FehlVersuche >= 11 Then g.DrawLine(b, 150, 90, 170, 75) 'rechter Arm
    13. End If
    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!
    mein Vorschlag aus post#4 ist auch nicht kürzer, aber insoweit schöner, dass ein Zeichen-Objekt entsteht, welches von der Paint-Routine unabhängig ist.

    Aber da nicht nur Linien zu zeichnen sind, sondern auch Kreise, greift mein Vorschlag mit der Liste von Linien zu kurz.
    Man bräuchte ein GraphicsPath - Objekt, um da die verschiedensten Zeichnungselemente drin anlegen zu können.

    Dieser Ansatz wäre dann eine Vorstufe zur Ausbildung auch beweglicher Zeichen-Objekte mit GDI.

    trex0113 schrieb:

    Aber gibt es nicht noch eine schönere, kürzere methode?
    Der Sinn der Paint-Routine besteht darin, dass sie "aus dem Kopf" das ganze Bild malen muss, was gerade erforderlich ist. Die Information, was zu malen ist, wird außen bereitgestellt, und bei Änderung dieser Information wird Invalidate() aufgerufen.
    Zunächst ist die Funktionalität wichtig, danach kommt die "Schönheit" nach Deinem Empfinden.
    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!