Für jedes Objekt eine neue Klasse

  • VB.NET

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

    Für jedes Objekt eine neue Klasse

    Hi, ich will mit einem kleinen Programm etwas testen. Es wird eine Box erstellt, die sich dann 100 Pixel weiter nach rechts bewegen soll, und dann wieder verschwinden. Die Anzahl der zu erstellenden Boxen wird mit dem Text einer Textbox definiert. Nur, wenn ich mehr als 2 Stück machen möchte, dann werden die Boxen nach der Reihe erstellt, sie bewegen sich und verschwinden... Einer nach dem anderen, aber nicht alle quasi gleichzeitig. Oder auf den Button, der der die Boxen erstellen soll, klicke, dann wird die Box, die davor erstellt wurde, einfach an der Position stehen bleiben und verschwindet auch nicht, weil es eben keine 100 Schritte macht, sondern einfach an der aktuellen Position stehen bleibt. ... Bisschen doof erklärt, gebe ich zu, aber ich poste einfach mal die Quellcode:

    Form1:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim dll As New pBlib
    3. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    4. Dim i As Integer = TextBox1.Text
    5. Dim w As Integer = 0
    6. While i > w
    7. w += 1
    8. dll = New pBlib
    9. dll.createPic()
    10. End While
    11. End Sub
    12. End Class


    Und die Klasse:

    VB.NET-Quellcode

    1. Public Class pBlib
    2. Dim pb As New PictureBox
    3. Public Sub createPic()
    4. pb = New PictureBox
    5. With pb
    6. .Location = New Point(150, 50)
    7. .Size = New Size(25, 25)
    8. .BackColor = Color.Black
    9. .Visible = True
    10. End With
    11. Form1.Controls.Add(pb)
    12. lifeTime()
    13. End Sub
    14. Dim life As Integer = 100
    15. Sub lifeTime()
    16. While life > 0
    17. Application.DoEvents()
    18. pb.Location = New Point(pb.Location.X + 1, pb.Location.Y)
    19. life = life - 1
    20. Threading.Thread.Sleep(10)
    21. End While
    22. Form1.Controls.Remove(pb)
    23. End Sub
    24. End Class
    Ja, und ich kann dir auch sagen, warum das so ist:

    VB.NET-Quellcode

    1. While life > 0
    2. Application.DoEvents()
    3. pb.Location = New Point(pb.Location.X + 1, pb.Location.Y)
    4. life = life - 1
    5. Threading.Thread.Sleep(10)
    6. End While

    Jedes mal, wenn du ein neues Objekt erzeugst, wird diese Schleife aufgerufen. Eine Schleife ist aber kein paralleler Vorgang, sondern ein wiederholter Sequentieller. Ein Application.DoEvents hilft also nichts, da eine SChleife nicht mit Events passiert, sondern eben (wie ich ja schon sagte) sequentiell. Wenn du möchtest, dass alle Objekte gleichzeitig arbeiten, musst du also unweigerlich auf Multithreading zurückgreifen. In deinem Fall wäre der Timers.Timer wohl am besten geeignet, eine Schleife ist eher fehl am Platz.

    Und nur mal nebenbei bemerkt:

    VB.NET-Quellcode

    1. While i > w
    2. w += 1
    3. dll = New pBlib
    4. dll.createPic()
    5. End While

    es gibt auch For-Schleifen...

    VB.NET-Quellcode

    1. Dim i As Integer = TextBox1.Text

    ... und Option Strict On.
    Der Code ist ein wunderschönes Negativbeispiel xD

    Zunächst schalte Option Strict ON ein (ganz oben über alles andere schreiben).
    Dim i As Integer = TextBox1.Text wird dann nichtmehr funktionieren - du musst den String zu Integer casten. Integer.TryParse ist hierfür geeignet, Cint() würde auch gehehen, wirft aber eine Exception wenn das casten schief geht.

    Die While-Schleife ist hier auch etwas fehl am Platz:

    VB.NET-Quellcode

    1. For w as integer = 0 to i
    2. 'mache irgendwas
    3. next


    wäre äquivalent zu deiner While-Schleife.

    Viel Schlimmer ist das, was du da in deiner Klasse pBlib treibst. "Form1.Controls.Add(pb)" funktioniert unter VB.NET leider ist aber kompletter Unsinn. Klassen sind ja bekanntermaßen Baupläne. Schreibst du:
    Dim meinHaus as Bauplan = new Bauplan
    heißt das nichts anderes als "meinHaus soll ein Objekt vom Typ Bauplan sein und jetzt bitteschön gebaut werden". Der Unterschied von Haus und Bauplan ist klar - in das eine kannst du Möbel stellen, in das andere nicht.
    In deiner Zeile Form1.Controls.Add(pb) stellst du also reale Möbel in ein Stück Papier - macht wenig Sinn aber der VB-Compiler bastelt sich da etwas zurecht, sodass es funktioniert. Forms haben Sonderstellung - bei anderen Klassen ist sowas afaik nicht möglich.


    DoEvents ist auch ein Zeichen für fehlerhafte Programmierung. Häufig sollte man die betroffene Routine in einen Thread auslagern - da würde ich dir aber aktuell von abraten.

    Threading.Thread.Sleep(10) In anderen Threads okay, wenn du im Gui-Thread arbeitest (tust du immer, es sei denn du benutzt Backgroundworker, Threads oder Async-Methoden bzw was es sonst noch gibt) aber schlecht. Timer sind hier oft eine Lösung - aber auch nicht die Lösung von allem!


    Bei dir ist es nun der Fall, dass all diese Quick&Dirty-Lösungen wie Zahnräder ineinander greifen und ein regelrechtes Eigenleben entwickeln. Mal ganz grob gesagt: lifeTime ist fast eine Endlosschleife. Da du alles im Gui-Thread machst blockiert diese Schleife alles. Du kannst also normalerweise nicht auf den Button klicken weil die GUI in der Schleife festhängt. DoEvents schafft dort eine Lücke. Du kannst eine weitere pBlib-Instanz erzeugen die eine weitere Picturebox steuert. Tja - aber eben auch noch im GUI-Thread. Box2 blockiert den Thread mit seiner lifeTime-Methode - also wird während dieser Zeit kein Code von Box1 ausgeführt usw.

    Eine brauchbare Lösung könnte ich dir nennen, allerdings ist es schlecht Controls zu "animieren". Besser per GDI zeichnen. Eine List(of DeineBox) könnte so in einem Timer abgearbeitet werden. Jede Box weiß wo sie ist und wohin sie sich bewegt. Du kannst also den nächste Position berechnen, zuweisen und am ende die aktualisierte Szene neuzeichnen.

    FreakJNS schrieb:

    Der Code ist ein wunderschönes Negativbeispiel xD
    So isses.

    Easly schrieb:

    VB.NET-Quellcode

    1. Dim pb As New PictureBox
    2. Public Sub createPic()
    3. pb = New PictureBox
    Wozu 2x New :?:

    Easly schrieb:

    VB.NET-Quellcode

    1. dll = New pBlib
    2. dll.createPic()
    Wenn iwas Created wird, dann nicht auf der Instanz, sondern auf der Klasse mit einer Shared Methode, was bei abgeleiteten Klassen sehr nützlich ist.
    Also

    VB.NET-Quellcode

    1. dll = pBlib.createPic()
    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!