Rechteck zeichnen -> Programm stürzt ab

  • VB.NET

Es gibt 29 Antworten in diesem Thema. Der letzte Beitrag () ist von FAtheone.

    Annonator schrieb:

    Wie wärs wenn du eine Bitmap erstellst, bezeichnest und dann der Picturebox als BackgroundImage unterschiebst.
    Dann hast du kein Me.Paint-Event, keine Und-Verknüpfung und keine Globale Bool'sche Variable auf die du achten müsstest.


    Hier ein möglicher Code, welcher es dir erlaubt auch unregelmäßige Vierecke zu zeichnen (sonst "DrawRectangle"):

    VB.NET-Quellcode

    1. Private Sub Viereck_Malen()
    2. Dim bmp As Bitmap = New Bitmap(Picturebox1.Width, Picturebox1.Height)
    3. Dim g As Graphics = Graphics.FromImage(bmp)
    4. Dim Punkt1X as Point = Textbox1.text
    5. Dim Punkt1Y as Point = Textbox2.text
    6. Dim Punkt2X as Point = Textbox3.text
    7. Dim Punkt2Y as Point = Textbox4.text
    8. Dim Punkt3X as Point = Textbox5.text
    9. Dim Punkt3Y as Point = Textbox6.text
    10. Dim Punkt4X as Point = Textbox7.text
    11. Dim Punkt4Y as Point = Textbox8.text
    12. g.DrawLine(Pens.Black, Punkt1X ,punkt1Y, Punkt2X ,punkt2Y)
    13. g.DrawLine(Pens.Black, Punkt2X ,punkt2Y, Punkt3X ,punkt3Y)
    14. g.DrawLine(Pens.Black, Punkt3X ,punkt3Y, Punkt4X ,punkt4Y)
    15. g.DrawLine(Pens.Black, Punkt4X ,punkt4Y, Punkt1X ,punkt1Y)
    16. Picturebox1.backgroundimage = bmp
    17. End Sub

    Wenn du willst das beim erneuten Zeichnen das vorherige erhaltenbleibt,schreib die 2. beiden Zeilen in der Sub, außerhalb der Sub.


    Beim verschieben außerhalb der Sub kommt zwar kein Error, allerdings dann beim Testen erhalte ich eine InnerException Fehlermeldung und das Debugging läuft zwar weiter, aber das Programm selbst öffnet sich nicht. Laut Meldung sei es ein Ungültiger Parameter in dieser Zeile:

    VB.NET-Quellcode

    1. 'Deine Parameter mit der Pictureboxhöhe und breite gingen leider auch nicht
    2. Dim bmp As Bitmap = New Bitmap("Bild", False)
    Müsste es nicht eher lauten:

    VB.NET-Quellcode

    1. Dim Startpunkt As New Point(Cint(TextBox1.Text), Cint(TextBox2.Text))
    2. Dim Endpunkt As New Point(Cint(TextBox3.Text), Cint(TextBox4.Text))
    3. g.DrawLine(Pens.Black, Startpunkt , Endpunkt)

    Soweit ich mich erinnere, erwartet Point zwei Werte, x und y.

    '######################################

    //Edit

    Versuch mal das:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim Startpunkte(100) As Point
    3. Dim Endpunkte(100) As Point
    4. Dim Zähler As Integer = 0
    5. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    6. End Sub
    7. Private Sub Malen()
    8. Dim bmp As Bitmap = New Bitmap(PictureBox1.Width, PictureBox1.Height)
    9. Dim g As Graphics = Graphics.FromImage(bmp)
    10. Dim NeuerStartpunkt As New Point(Cint(TextBox1.Text), Cint(TextBox2.Text))
    11. Dim NeuerEndpunkt As New Point(Cint(TextBox3.Text), Cint(TextBox4.Text))
    12. Startpunkte(Zähler) = NeuerStartpunkt
    13. Endpunkte(Zähler) = NeuerEndpunkt
    14. If Zähler > 0 Then
    15. For i As Integer = 0 To Zähler 'Lese die bisherigen Linien aus dem Array
    16. g.DrawLine(Pens.Black, Startpunkte(i), Endpunkte(i))
    17. Next
    18. End If
    19. g.DrawLine(Pens.Black, NeuerStartpunkt, NeuerEndpunkt)
    20. PictureBox1.BackgroundImage = bmp
    21. Zähler += 1 'Zeiger für neuen Eintrag ins Array erhöhen
    22. TextBox1.Focus() 'Cursor wieder in erste Textbox
    23. End Sub
    24. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    25. Malen()
    26. End Sub
    27. End Class

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Unwesen“ ()

    @Annonator,
    bei deinem Code wird mir leicht schwummerig um die Rosette... ;(
    Dim Punkt1X as Point = Textbox1.text Seid wann weist man einem Point-Objekt einen String zu? :cursing:
    Auch das hier: Dim Punkt2XY As New Point(TextBox3.Text, TextBox4.Text) ist nicht besser.
    Schon was von Option Strict O gehört?
    Wenn, dann Cint(TextboxXY.Text)...
    Außerdem ist das ständige erzeugen von Graphics-Objekten nich sooo schön.
    Besser is:

    VB.NET-Quellcode

    1. Using g g As Graphics = Graphics.FromImage(bmp)
    2. 'Codeür das Zeichnen
    3. End Using
    Alternativ geht natürlich auch Dispose
    Der Weg mit dem Bitmap ist natürlich schon der richtige Ansatz, ich würde trotzdem grundsätzlich auf die Picturebox verzichten,da das Zeichnen mit dem Paint-Event mit Drawimage definitiv performanter ist. Letztlich ruft die Picturebox auch nur ihr Paint-Event auf.
    Und ich bleibe dabei, ein Timer ist dafür absoluter Blödsinn. Man kann auch eine einzige Event-Sub für alle Textboxen definieren, in dem man die Handler dahintersetzt oder im Designer das gleiche Event zuordnet. Im sender ist dann die jeweilige Textbox enthalten, so dass dort die Überprüfung auf gültige Eingaben erfolgen kann.
    Weiterer Vorteil:
    Mit dem Zeichnen mehrerer Bitmaps nacheinander auf die Form hat man mehrere "Ebenen" oder "Folien" zur Verfügung (Hintergrund etc.).

    Edit:
    Wegen Langerweile hier ein ungetesteter Code für eine Eingabeprüfung von Textboxen auf Integer, die problemlos auf andere Datentypen umgebaut werden kann.

    VB.NET-Quellcode

    1. 'Im Designer in die Tag-Eigenschaften der TBs "0" schreiben.
    2. 'Im Textchanged-Event
    3. Dim TB as New Textbox = DirectCast(sender, Textbox)
    4. Dim _Int as Integer
    5. If Integer.Tryparse(TB.Text, _Int) Then 'Wenn sich die Eingabe Integer umwandeln lässt
    6. TB.Tag = _Int 'Integerwert in die Tag-Eigenschaft vom Typ Objekt zwischenspeichern
    7. End If
    8. TB.Text = CInt(TB.Tag).toString 'Zurückschreiben des Zwischenspeichers in die Text-Eigenschaft
    9. 'Bei einer ungültigen Eingabe wird dadurch die alte (letzte) Eingabe wieder hergestellt
    10. Else

    Fiel Fergnügen beim rumprobieren
    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:

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

    Ich habe das Beispiel jetzt etwas erweitert und daraus quasi ein Grundgerüst für ein Malprogramm geschaffen. Die einzige Grenze die es bislang hat, ist dass maximal 100 Rechtecke(Der Arrayindex eben) gezeichnet werden können. Und ich weiß ja nicht, wieviel der User schlussendlich malen wird und kann somit den Arrayindex nicht im vorraus bestimmen. Gibt es Methoden eine Art "Unendlichen" Array zu erstellen, und das dabei wenn möglich nicht auf Kosten der Performance(Der Arbeitsspeicher steigt nämlich bei Arrayindex 300 um satte 300MB) ?

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim Startpunkte(100) As Rectangle
    3. 'Unser Array
    4. Dim Zähler As Integer = 0
    5. 'Mauskoordinaten
    6. Dim MouseX, MouseY As Integer
    7. 'Überprüfung ob gezeichnet wird
    8. Dim IsDrawing As Boolean
    9. 'Lila Farbe
    10. Dim Lila As New System.Drawing.Pen(Color.Violet, 5)
    11. Private Sub Malen()
    12. Dim bmp As Bitmap = New Bitmap(PictureBox1.Width, PictureBox1.Height)
    13. Dim g As Graphics = Graphics.FromImage(bmp)
    14. Dim NeuerStartpunkt As New Rectangle(MouseX, MouseY, 5, 5)
    15. Startpunkte(Zähler) = NeuerStartpunkt
    16. If Zähler > 0 Then
    17. For i As Integer = 0 To Zähler 'Alle vorherigen Inhalte lesen
    18. g.DrawRectangle(Lila, Startpunkte(i))
    19. Next
    20. End If
    21. g.DrawRectangle(Lila, NeuerStartpunkt)
    22. PictureBox1.BackgroundImage = bmp
    23. Zähler += 1 'Zeiger für neuen Eintrag ins Array erhöhen
    24. End Sub
    25. Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    26. IsDrawing = True
    27. MouseX = e.X
    28. MouseY = e.Y
    29. Malen()
    30. End Sub
    31. Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    32. If (IsDrawing = True) Then
    33. MouseX = e.X
    34. MouseY = e.Y
    35. Malen()
    36. End If
    37. End Sub
    38. Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
    39. IsDrawing = False
    40. End Sub
    41. End Class


    @Vatter: Na gut, überredet, dann eben kein Timer ;)
    Hmpf. Option Strict benutze ich beim erstellen so ungerne, das lasse ich zum Schluss checken. Aber ich hatte ein paar Minuten später den Code noch stellenweise überarbeitet und ihm eine Strict Fassung per pn geschickt. Was die Timer angeht, das mag ja für dieses Vorhaben überflüssig sein, aber bei sowas wie im Anhang macht es doch Sinn..^^ Zumindest wüsste ich es nicht besser.

    Zum angehängten File: Könnte zu nem Error beim Start kommen, aber sollte eigentlich ausführbar sein.
    Dateien
    • DYCP(test).zip

      (10,52 kB, 59 mal heruntergeladen, zuletzt: )
    Okay, das letzte Beispiel war vielleicht nicht ganz durchdacht. (Das ist zwar auch nur Pfusch, aber eventuell bringts dir ja neue Erkenntnisse.):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. 'Dim Startpunkte(100) As Rectangle 'Unnötig
    3. 'Unser Array
    4. 'Dim Zähler As Integer = 0 'Unnötig
    5. 'Mauskoordinaten
    6. Dim MouseX, MouseY As Integer
    7. 'Überprüfung ob gezeichnet wird
    8. Dim IsDrawing As Boolean
    9. 'Lila Farbe
    10. Dim Lila As New System.Drawing.Pen(Color.Violet, 5)
    11. Dim bmp As Bitmap = New Bitmap(640, 480)
    12. Private Sub Malen()
    13. Dim g As Graphics = Graphics.FromImage(bmp)
    14. Dim NeuerStartpunkt As New Rectangle(MouseX, MouseY, 5, 5)
    15. 'Startpunkte(Zähler) = NeuerStartpunkt
    16. 'If Zähler > 0 Then
    17. ' For i As Integer = 0 To Zähler 'Alle vorherigen Inhalte lesen
    18. ' g.DrawRectangle(Lila, Startpunkte(i))
    19. ' Next
    20. 'End If
    21. g.DrawRectangle(Lila, NeuerStartpunkt)
    22. PictureBox1.BackgroundImage = bmp
    23. 'Zähler += 1 'Zeiger für neuen Eintrag ins Array erhöhen
    24. End Sub
    25. Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    26. IsDrawing = True
    27. MouseX = e.X
    28. MouseY = e.Y
    29. Malen()
    30. PictureBox1.Invalidate()
    31. End Sub
    32. Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    33. If (IsDrawing = True) Then
    34. MouseX = e.X
    35. MouseY = e.Y
    36. Malen()
    37. PictureBox1.Invalidate()
    38. End If
    39. End Sub
    40. Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
    41. IsDrawing = False
    42. End Sub
    43. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    44. End Sub
    45. End Class


    Ein paar kleine Änderungen, so dürfte das ein paar Einschränkungen beseitigen. Aufräumen kannste selber... XD

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

    Jetzt hab ich den Fehler gefunden. Ein Bitmap darf global sein, das Graphics-Objekt allerdings nicht. Nun hab ich es mal geschafft, das ganze zum malen zu bringen. Nur eine Umsetzugn für einen Radiergummi muss ich mir noch überlegen. Mit Transparenter Farbe habe ich es schon versucht, aber das ging nicht :/ Das Hauptproblem ist allerdings eher die Tatsache, dass ich vom Bitmap nicht die Breite und die Höhe zur Laufzeit ändern kann(es soll sich immer dieselben Maße wie eine Picturebox haben) Ist das bei Bitmaps überhaupt möglich? Breite und Höhe sind ja Read-only :/
    Öhm Ja, da hab ich einige Fehler gemacht, tut mir wirklich Leid, es muss natürlich heißen:

    VB.NET-Quellcode

    1. Dim Punkt1X as String = Textbox1.Text
    2. Dim Punkt1Y as String = Textbox2.Text

    wahlweise auch

    VB.NET-Quellcode

    1. Dim Punkt1 as Point = New Point(Textbox1.Text,Textbox2.Text)


    Und wenn du dass außerhalb der Sub schreibst darfst du dort keine relativen Angaben machen, also nur Zahlen.

    VB.NET-Quellcode

    1. Dim bmp As Bitmap = New Bitmap(300,300) 'Wenn du eine 300px * 300px Picturebox hast.
    2. Dim g As Graphics = Graphics.FromImage(bmp)

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