Grafikverarbeitung in einem Thread

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von tron25.

    Grafikverarbeitung in einem Thread

    Hallo,
    ich habe ein Programm, welches ein Arbeitsblatt mit Seitenrändern anzeigt. Die Arbeitsoberfläche kann in der Größe verändert werden. Die Oberfläche wird in einer Picturebox (SichtfensterPicture) gezeichnet. Bis jetzt hatte ich zum Aktualisieren folgende Funktion (Die Funktion ist für die bessere Veranschaulichung stark verkürzt):

    VB.NET-Quellcode

    1. Public Sub GrafikAufbauen()
    2. 'Wenn eine vorherige Instanz dieser funktion bereits ausgeführt wird,
    3. 'so wird der aktuelle Durchgang verlassen.
    4. If Ausfuehren = False Then
    5. Exit Sub
    6. Else
    7. Ausfuehren = False
    8. End If
    9. SichtfensterObjekt.Clear(Programmfarben(Fensterhintergrundfarbe))
    10. 'Der Arbeitshintergrund wird gezeichnet. Nachdem danach die Arbeitsbereiche
    11. 'gezeichnet werden, bleiben nur noch die Seitenränder sichtbar.
    12. If Seitenbreite * ZoomFaktor < SichtfensterPicture.ClientSize.Width Then
    13. Zeichenbereich.Links = (SichtfensterPicture.ClientSize.Width - (Seitenbreite * ZoomFaktor)) / 2
    14. Zeichenbereich.Breite = Seitenbreite * ZoomFaktor
    15. Else
    16. Zeichenbereich.Links = 0
    17. Zeichenbereich.Breite = SichtfensterPicture.ClientSize.Width
    18. End If
    19. If Seitenhoehe * ZoomFaktor < SichtfensterPicture.ClientSize.Height Then
    20. Zeichenbereich.Oben = (SichtfensterPicture.ClientSize.Height - (Seitenhoehe * ZoomFaktor)) / 2
    21. Zeichenbereich.Hoehe = Seitenhoehe * ZoomFaktor
    22. Else
    23. Zeichenbereich.Oben = 0
    24. Zeichenbereich.Hoehe = SichtfensterPicture.ClientSize.Height
    25. End If
    26. Using Ausgefuellt = New SolidBrush(Programmfarben(Seitenraenderfarbe))
    27. Try
    28. SichtfensterObjekt.FillRectangle(Ausgefuellt, New Rectangle(Zeichenbereich.Links, Zeichenbereich.Oben, Zeichenbereich.Breite, Zeichenbereich.Hoehe))
    29. Catch myerror As Exception
    30. End Try
    31. End Using
    32. ...
    33. SichtfensterPicture.Image = SichtfensterPuffer
    34. end sub


    Jetzt möchte ich diese Funktion in ein Thread auslagern. Dazu habe ich eine neue Klasse namens OberflaecheKlasse erstellt.

    VB.NET-Quellcode

    1. Imports System.Threading
    2. Imports System.Drawing.Imaging
    3. Public Class OberflaecheKlasse
    4. Implements IDisposable
    5. Private Oberflaeche As Bitmap = New Bitmap(1, 1)
    6. Private OberflaecheObjekt As Graphics = Graphics.FromImage(Oberflaeche)
    7. Private GrafikErstellen As Thread
    8. Public Event GrafikAufbauen(Grafik As Bitmap)
    9. Private Ausfuehren As Boolean
    10. Public Sub GrafikaufbauStarten()
    11. If Not GrafikErstellen Is Nothing Then
    12. Throw New Exception("Ich mach doch schon....")
    13. End If
    14. Ausfuehren = True
    15. GrafikErstellen = New Thread(AddressOf OberflaecheZeichnen)
    16. GrafikErstellen.Start()
    17. End Sub
    18. Public Sub GrafikaufbauStoppen()
    19. Ausfuehren = False
    20. End Sub
    21. Public Sub OberflaecheZeichnen()
    22. While Ausfuehren
    23. Oberflaeche = New Bitmap(Oberflaechenbreite, Oberflaechenhoehe)
    24. OberflaecheObjekt = Graphics.FromImage(Oberflaeche)
    25. OberflaecheObjekt.Clear(Programmfarben(Fensterhintergrundfarbe))
    26. 'Der Arbeitshintergrund wird gezeichnet. Nachdem danach die Arbeitsbereiche
    27. 'gezeichnet werden, bleiben nur noch die Seitenränder sichtbar.
    28. If Seitenbreite * ZoomFaktor < Oberflaechenbreite Then
    29. Zeichenbereich.Links = (Oberflaechenbreite - (Seitenbreite * ZoomFaktor)) / 2
    30. Zeichenbereich.Breite = Seitenbreite * ZoomFaktor
    31. Else
    32. Zeichenbereich.Links = 0
    33. Zeichenbereich.Breite = Oberflaechenbreite
    34. End If
    35. If Seitenhoehe * ZoomFaktor < Oberflaechenhoehe Then
    36. Zeichenbereich.Oben = (Oberflaechenhoehe - (Seitenhoehe * ZoomFaktor)) / 2
    37. Zeichenbereich.Hoehe = Seitenhoehe * ZoomFaktor
    38. Else
    39. Zeichenbereich.Oben = 0
    40. Zeichenbereich.Hoehe = Oberflaechenhoehe
    41. End If
    42. Using Ausgefuellt = New SolidBrush(Programmfarben(Seitenraenderfarbe))
    43. Try
    44. OberflaecheObjekt.FillRectangle(Ausgefuellt, New Rectangle(Zeichenbereich.Links, Zeichenbereich.Oben, Zeichenbereich.Breite, Zeichenbereich.Hoehe))
    45. Catch myerror As Exception
    46. End Try
    47. End Using
    48. ...
    49. RaiseEvent GrafikAufbauen(Oberflaeche)
    50. Thread.Sleep(10)
    51. End While
    52. End Sub
    53. End Class


    Im Hauptformular habe ich Folgendes hinzugefügt:

    VB.NET-Quellcode

    1. 'Im Klassenkopf
    2. Private WithEvents Oberflaeche As New OberflaecheKlasse
    3. 'Innerhalb der Klasse
    4. Private Sub OberflaecheAnzeigen(Grafik As Bitmap) Handles Oberflaeche.GrafikAufbauen
    5. SichtfensterPicture.Image = Grafik
    6. End Sub
    7. Private Sub SichtfensterPicture_Resize(sender As Object, e As EventArgs) Handles SichtfensterPicture.Resize
    8. Oberflaechenbreite = SichtfensterPicture.ClientSize.Width
    9. Oberflaechenhoehe = SichtfensterPicture.ClientSize.Height
    10. End Sub


    Nun habe ich schon verstanden, dass ich aus dem Thread heraus nicht die Größen der Picturebox verwenden kann. Daher habe ich die Variablen "Oberflaechenbreite", und "Oberflaechenhoehe" in einem globalen Modul erzeugt. Sie werden jedesmal, wenn sich die Größe der Picturebox ändert, angepaßt. Nun bekomme ich folgenden Fehler:
    error BC30519: Fehler bei der Überladungsauflösung, da keine zugreifbare "New" ohne einschränkende Konvertierung aufgerufen werden kann:
    Es wir die folgende Zeile markiert:

    VB.NET-Quellcode

    1. Oberflaeche = New Bitmap(Oberflaechenbreite, Oberflaechenhoehe)


    Wenn ich statt dessen zahlen in die Klammern schreibe, funktioniert es.

    Hat jemand eine Idee, woran es liegen kann?
    @tron25 Mach aus Deinen Snippets ein kleines Projekt (Strict On), das compiliert, und hänge es bereinigt (ohne bin, obj und vs-Verzeichnisse) und gezippt an.
    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!
    Von welchem Datentyp sind denn Oberflaechenbreite und Oberflaechenhoehe? Die müssen schon zu einem Bitmap-Konstruktoraufruf passen, sonst weiß der Compiler nicht, was er machen soll.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Sorry, dass es etwas gedauert hat, aber ich hatte Probleme mit VS. Es ist immer abgestürzt, wenn ich ein Steuerelement hinzufügen wollte. Nach unzähligen Neuinstallationen von VS hat schließlich nur eine komplette Windows-Installation geholfen.

    So, hier kommt ein kleines Program mit dem Nötigsten.
    Dateien
    • WindowsApp1.zip

      (72,59 kB, 85 mal heruntergeladen, zuletzt: )
    @tron25 Lesen bildet:

    RodFromGermany schrieb:

    und hänge es bereinigt (ohne bin, obj und vs-Verzeichnisse)
    72588 Bytes => 14820 Bytes
    ====
    Ich hab ein wenig rungeklickert, die Größe des Fensters geändert und es minimiert.
    Hier eine Exception:
    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!

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

    @tron25 Die Größe des ClientSize ist {0,0} (das ist nicht der Text, war aber die Meldung).
    Ich glaube das kam nach Minimierung und Normal-Ansicht.
    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!
    Um das etwas zu verdeutlichen, ich habe einen Sehrest von weniger als 5%. Zudem habe ich ein sehr eingeschränktes Gesichtsfeld. Stell dir vor, du müstest eine Grafik durch einen McDonald's-Strohhalm betrachten. Zudem ist das Bild sehr dunkel und verschwommen. Sorry, aber wenn es nicht geht, dann geht es nicht.
    Das bild ist wirklich fast bildschirmfüllend groß und vor allem ist es werder dunkel noch verschwommen, irgend etwas scheint mit deinem Setting nicht zu stimmen.
    Das einzige was du machen musst, ist drauf klicken. Ich schreibe das hier auch nur, weil "dunkel und verschwommen" einfach nicht stimmt, egal wie gut oder schlecht du sehen kannst. Allerdings ist es ein Bild und vorlesen lassen wird wohl nicht gehen.

    tron25 schrieb:

    Um das etwas zu verdeutlichen, ich habe einen Sehrest von weniger als 5%.
    ok, dann hilft draufklicksen wohl nicht.
    Ich hatte die Hoffnung, du kenntest nur das Klickse-Feature nicht, und würdest versuchen, das Bild in der Vorschau zu erkennen
    also das Bild zeigt diesen Code:

    VB.NET-Quellcode

    1. Private Sub PunktBilderFormular_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    2. ZoomScroll.Height = Me.ClientSize.Width / 30
    3. ZoomScroll.Width = Me.ClientSize.Width - ZoomScroll.Height
    4. ZoomScroll.Left = 0
    5. ZoomScroll.Top = 0
    6. SichtfensterPicture.Left = 0
    7. SichtfensterPicture.Top = ZoomScroll.Bottom
    8. SichtfensterPicture.Height = Me.ClientSize.Height - (ZoomScroll.Height * 2)
    9. SichtfensterPicture.Width = ZoomScroll.Width
    10. BildflaecheHorizontalScroll.Top = SichtfensterPicture.Bottom
    11. BildflaecheHorizontalScroll.Left = SichtfensterPicture.Left
    12. BildflaecheHorizontalScroll.Width = SichtfensterPicture.Width
    13. BildflaecheHorizontalScroll.Height = ZoomScroll.Height
    14. BildflaecheVertikalScroll.Top = ZoomScroll.Bottom
    15. BildflaecheVertikalScroll.Left = SichtfensterPicture.Right
    16. BildflaecheVertikalScroll.Width = ZoomScroll.Height
    17. BildflaecheVertikalScroll.Height = SichtfensterPicture.Height
    18. SichtfensterPuffer = New Bitmap(SichtfensterPicture.ClientSize.Width, SichtfensterPicture.ClientSize.Height) 'hier tritt eine ArgumentException auf
    19. SichtfensterObjekt = Graphics.FromImage(SichtfensterPuffer)
    20. SeiteEinrichten()
    21. End Sub
    Die ArgumentException tritt auf, wenn man das Fenster minimiert.
    Hallo Dksksm,
    also, dass das Bild in Ordnung ist, glaube ich dir. Es geht ja auch um meine Augen. Stell dir vor, du trägst eine etwa 90 % verdunkelte Sonnenbrille. dann klebst du zwei Blätter auf die Gläser in denen jeweils in der Mitte nur ein kleines Loch ausgestanzt ist. Darüber klebst du noch zwei bis drei Klarsichtfolien, sodass das Bild verschwommen auf deine Netzhaut trifft. Das hat außerdem zur Folge, dass bei Sonneneinstrahlung alles so hell wird, dass du kaum eine weiße Hauswand von einem Scheunentor unterscheiden kannst.

    Nun zum eigentlichen Problem, welches nicht mehr eines ist:
    Erstens habe ich falsche Werte eingetragen und zweitens erwartet die "New Bitmap"-Funktion Integer. Die korrekten Variablen "Oberflaechenbreite", und "Oberflaechenhoehe" waren aber als Double deklariert.
    Hier nochmal die korrekten Funktionen:

    VB.NET-Quellcode

    1. Imports System.Threading
    2. Imports System.Drawing.Imaging
    3. Public Class OberflaecheKlasse
    4. Implements IDisposable
    5. Private GrafikErstellen As Thread
    6. Public Event GrafikAufbauen(Grafik As Bitmap)
    7. Private Ausfuehren As Boolean
    8. Private Oberflaeche As Bitmap = New Bitmap(1, 1)
    9. Private OberflaecheObjekt As Graphics = Graphics.FromImage(Oberflaeche)
    10. Public Sub OberflaecheZeichnen()
    11. While Ausfuehren
    12. If Oberflaechenbreite > 0 And Oberflaechenhoehe > 0 Then
    13. Oberflaeche = New Bitmap(Oberflaechenbreite, Oberflaechenhoehe)
    14. OberflaecheObjekt = Graphics.FromImage(Oberflaeche)
    15. OberflaecheObjekt.Clear(Programmfarben(Fensterhintergrundfarbe))
    16. 'Der Arbeitshintergrund wird gezeichnet. Nachdem danach die Arbeitsbereiche
    17. 'gezeichnet werden, bleiben nur noch die Seitenränder sichtbar.
    18. If Seitenbreite * ZoomFaktor < Oberflaechenbreite Then
    19. Zeichenbereich.Links = (Oberflaechenbreite - (Seitenbreite * ZoomFaktor)) / 2
    20. Zeichenbereich.Breite = Seitenbreite * ZoomFaktor
    21. Else
    22. Zeichenbereich.Links = 0
    23. Zeichenbereich.Breite = Oberflaechenbreite
    24. End If
    25. If Seitenhoehe * ZoomFaktor < Oberflaechenhoehe Then
    26. Zeichenbereich.Oben = (Oberflaechenhoehe - (Seitenhoehe * ZoomFaktor)) / 2
    27. Zeichenbereich.Hoehe = Seitenhoehe * ZoomFaktor
    28. Else
    29. Zeichenbereich.Oben = 0
    30. Zeichenbereich.Hoehe = Oberflaechenhoehe
    31. End If
    32. Using Ausgefuellt = New SolidBrush(Programmfarben(Seitenraenderfarbe))
    33. Try
    34. OberflaecheObjekt.FillRectangle(Ausgefuellt, New Rectangle(Zeichenbereich.Links, Zeichenbereich.Oben, Zeichenbereich.Breite, Zeichenbereich.Hoehe))
    35. Catch myerror As Exception
    36. End Try
    37. End Using
    38. RaiseEvent GrafikAufbauen(Oberflaeche)
    39. End If
    40. Thread.Sleep(10)
    41. End While
    42. End Sub
    43. End Class


    VB.NET-Quellcode

    1. Public Class PunktBilderFormular
    2. Private WithEvents Oberflaeche As New OberflaecheKlasse
    3. Private Sub PunktBilderFormular_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. 'Die Listen für Farben werden gefüllt.
    5. Programmfarben.Add(Color.Black)
    6. Programmfarben.Add(Color.Red)
    7. Programmfarben.Add(Color.White)
    8. Farben.Add("Schwarz")
    9. Farben.Add("Rot")
    10. Farben.Add("Weiss")
    11. 'Jetzt werden Einstellungen vordefiniert.
    12. ZoomFaktor = 1
    13. Fensterhintergrundfarbe = Farben.IndexOf("Schwarz")
    14. Seitenraenderfarbe = Farben.IndexOf("Rot")
    15. Punktbildhintergrundfarbe = Farben.IndexOf("Weiss")
    16. ZoomScroll.Value = ZoomFaktor
    17. Seitenbreite = 210
    18. Seitenhoehe = 297
    19. ObererRand = 5
    20. LinkerRand = 15
    21. RechterRand = 5
    22. UntererRand = 5
    23. PunktBilderFormular_Resize(sender, EventArgs.Empty)
    24. Oberflaeche.GrafikaufbauStarten()
    25. End Sub
    26. Private Sub PunktBilderFormular_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    27. ZoomScroll.Height = Me.ClientSize.Width / 30
    28. ZoomScroll.Width = Me.ClientSize.Width - ZoomScroll.Height
    29. ZoomScroll.Left = 0
    30. ZoomScroll.Top = 0
    31. SichtfensterPicture.Left = 0
    32. SichtfensterPicture.Top = ZoomScroll.Bottom
    33. SichtfensterPicture.Height = Me.ClientSize.Height - (ZoomScroll.Height * 2)
    34. SichtfensterPicture.Width = ZoomScroll.Width
    35. BildflaecheHorizontalScroll.Top = SichtfensterPicture.Bottom
    36. BildflaecheHorizontalScroll.Left = SichtfensterPicture.Left
    37. BildflaecheHorizontalScroll.Width = SichtfensterPicture.Width
    38. BildflaecheHorizontalScroll.Height = ZoomScroll.Height
    39. BildflaecheVertikalScroll.Top = ZoomScroll.Bottom
    40. BildflaecheVertikalScroll.Left = SichtfensterPicture.Right
    41. BildflaecheVertikalScroll.Width = ZoomScroll.Height
    42. BildflaecheVertikalScroll.Height = SichtfensterPicture.Height
    43. SeiteEinrichten()
    44. End Sub
    45. Public Sub SeiteEinrichten()
    46. If ObererRand > (Seitenhoehe / 2) - 1 Then
    47. ObererRand = (Seitenhoehe / 2) - 1
    48. End If
    49. If UntererRand > (Seitenhoehe / 2) - 1 Then
    50. UntererRand = (Seitenhoehe / 2) - 1
    51. End If
    52. If LinkerRand > (Seitenbreite / 2) - 1 Then
    53. LinkerRand = (Seitenbreite / 2) - 1
    54. End If
    55. If RechterRand > (Seitenbreite / 2) - 1 Then
    56. RechterRand = (Seitenbreite / 2) - 1
    57. End If
    58. If ZoomFaktor * Seitenbreite > SichtfensterPicture.ClientSize.Width Then
    59. BildflaecheHorizontalScroll.Maximum = Seitenbreite * ZoomFaktor - SichtfensterPicture.ClientSize.Width
    60. Else
    61. BildflaecheHorizontalScroll.Maximum = 0
    62. End If
    63. If Seitenhoehe * ZoomFaktor > SichtfensterPicture.ClientSize.Height Then
    64. BildflaecheVertikalScroll.Maximum = Seitenhoehe * ZoomFaktor - SichtfensterPicture.ClientSize.Height
    65. Else
    66. BildflaecheVertikalScroll.Maximum = 0
    67. End If
    68. End Sub
    69. Private Sub OberflaecheAnzeigen(Grafik As Bitmap) Handles Oberflaeche.GrafikAufbauen
    70. SichtfensterPicture.Image = Grafik
    71. End Sub
    72. Private Sub SichtfensterPicture_Resize(sender As Object, e As EventArgs) Handles SichtfensterPicture.Resize
    73. Oberflaechenbreite = SichtfensterPicture.ClientSize.Width
    74. Oberflaechenhoehe = SichtfensterPicture.ClientSize.Height
    75. End Sub
    76. Private Sub ZoomScroll_Scroll(sender As Object, e As ScrollEventArgs) Handles ZoomScroll.Scroll
    77. ZoomFaktor = ZoomScroll.Value
    78. End Sub
    79. End Class


    VB.NET-Quellcode

    1. Module GlobaleVariablen
    2. Public Structure Grafikrechteck
    3. Public Links As Integer
    4. Public Oben As Integer
    5. Public Breite As Integer
    6. Public Hoehe As Integer
    7. End Structure
    8. Public Zeichenbereich As Grafikrechteck
    9. Public Sichtfenster As Grafikrechteck
    10. Public SichtfensterPuffer As Bitmap = New Bitmap(1, 1)
    11. Public SichtfensterObjekt As Graphics = Graphics.FromImage(SichtfensterPuffer)
    12. Public Oberflaechenbreite As Integer
    13. Public Oberflaechenhoehe As Integer
    14. 'Farben
    15. Public Programmfarben As New List(Of Color)
    16. Public Farben As New List(Of String)
    17. Public Fensterhintergrundfarbe As Integer
    18. Public Seitenraenderfarbe As Integer
    19. Public Punktbildhintergrundfarbe As Integer
    20. Public ZoomFaktor As Integer
    21. Public Seitenhoehe As Integer
    22. Public Seitenbreite As Integer
    23. Public ObererRand As Integer
    24. Public UntererRand As Integer
    25. Public LinkerRand As Integer
    26. Public RechterRand As Integer
    27. End Module


    Das Problem war tatsächlich meine eigene Schuselligkeit. Trotzdem vielen Dank für eure Mühe. Ich bin Realist, daher "Auf wiedersehen. bzw. -lesen"
    Die Grafikanzeige funktioniert jetzt fast so, wie ich es gerne hätte. Eine Sache stöhrt mich doch. In meinem obigen Beispiel lasse ich die Breite und Höhe von "SichtfensterPicture" beim resizen in die Variablen "Oberflaechenbreite" und "Oberflaechenhoehe" schreiben. Da diese Variablen in einem globalen Modul deklariert werden, kann ich von überall darauf zugreifen. In der Klasse für die Oberflächenberechnung frage ich einige "Checked"-Stati von Menüpunkten aus dem Hauptfenster ab. Beispiel:

    VB.NET-Quellcode

    1. 'Wenn die Brailleanzeige sichtbar ist und sich im sichtbaren Bereich
    2. 'befindet, wird sie gezeichnet.
    3. If PunktbilderFormular.BraillemarkierungMenue.Checked Then
    4. If Seitenhoehe * ZoomFaktor <= Oberflaechenhoehe Then
    5. Braille.GrafikOben = ((Oberflaechenhoehe - (Seitenhoehe * ZoomFaktor)) / 2) + (ObererRand + (Braille.ArrayOben * Punktgroesse) * ZoomFaktor)
    6. '.....
    7. End If
    8. Using Ausgefuellt = New SolidBrush(Programmfarben(BraillemarkierungHintergrundfarbe))
    9. Try
    10. OberflaecheObjekt.FillRectangle(Ausgefuellt, New RectangleF(Zeichenbereich.Links, Zeichenbereich.Oben, Zeichenbereich.Breite, Zeichenbereich.Hoehe))
    11. Catch myerror As Exception
    12. End Try
    13. End Using
    14. End If


    Beim Ausführen erschein keine Fehlermeldung. Allerdings, wenn ich solch einen Wert überwachen möchte, bekomme ich die Meldung:
    error BC30469: Der Verweis auf einen nicht freigegebenen Member erfordert einen Objektverweis.
    Wie kann ein Menüpunkt freigegeben werden?
    Eine weitere Möglichkeit wäre, für solche Aktionen immer eine globale Variable zu verwenden. Allerdings gefällt mir diese Lösung nicht, da mann ganz schnell viel zu viele Variablen hat.