Klassische Eventschleife oder BindEvent/Callbacks?

Anfängerfragen zum Programmieren mit PureBasic.
Istvan42
Beiträge: 16
Registriert: 15.12.2019 16:59
Computerausstattung: MacOS Sonoma (M1), PureBasic 6.03 LTS (MacOS X - x64)

Klassische Eventschleife oder BindEvent/Callbacks?

Beitrag von Istvan42 »

Hallo zusammen,

ich frage mich als Anfänger, welche Methode für die Ereignisabfrage die geeigente ist.

Dazu mal zwei einfache Beispiele. Listing 1 mit der "klassischen" Eventschleife und Listing 2 mit BindEvent und Callbacks.

Code: Alles auswählen

; Listing 1
; Ereignisabfrage in Schleife mit Select und ggf. IF

EnableExplicit

Declare OpenMyWindow()
Declare ProgramEnd()
Declare ButtonAction()

Enumeration 
  #Window_0
  #Button_0
EndEnumeration

Define Event.i

Procedure OpenMyWindow()
  OpenWindow(#Window_0, #PB_Ignore, #PB_Ignore, 350, 140, "My Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(#Button_0, 110, 90, 110, 30, "Dürck mich!")
EndProcedure

Procedure ProgramEnd()  
  End
EndProcedure

Procedure ButtonAction()
  MessageRequester("Info", "Du hast mich gedrückt!", #PB_MessageRequester_Info)
EndProcedure

OpenMyWindow()

Repeat
  Event = WaitWindowEvent() 
  Select Event  
    Case #PB_Event_CloseWindow
      If EventWindow() = #Window_0 ; falls mehrere Fenster möglich sind
        ProgramEnd()
      EndIf
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #Button_0
          ButtonAction()
      EndSelect
  EndSelect  
ForEver

Code: Alles auswählen

; Listing 2
; Ereignis mit Callback


EnableExplicit

Declare OpenMyWindow()
Declare ProgramEnd()
Declare ButtonAction()

Enumeration 
  #Window_0
  #Button_0
EndEnumeration

Define Event.i

Procedure OpenMyWindow()
  OpenWindow(#Window_0, #PB_Ignore, #PB_Ignore, 350, 140, "My Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(#Button_0, 110, 90, 110, 30, "Dürck mich!")
  BindEvent(#PB_Event_CloseWindow, @ProgramEnd(), #Window_0)
  ;BindGadgetEvent(#Button_0, @ButtonAction(), #PB_EventType_LeftClick)
  BindEvent(#PB_Event_Gadget, @ButtonAction(), #Window_0, #Button_0, #PB_EventType_LeftClick)
EndProcedure

Procedure ProgramEnd()  
  End
EndProcedure

Procedure ButtonAction()
  MessageRequester("Info", "Du hast mich gedrückt!", #PB_MessageRequester_Info)
EndProcedure

OpenMyWindow()

Repeat
  WaitWindowEvent() 
ForEver

Mir persönlich gefällt die Methode aus Listing 2 wesentlich besser, da auch bei vielen komplexen Fenstern, keine Monster-Eventschleife entsteht (ggf. noch mit einem Mix aus Select/if-Anweisungen). Ich bin mir aber nicht sicher, ob die Methode in Listing 2 nicht auch Nachteile mit sich bringt. Bei Echtzeitereignissen soll man wohl grundsätzlich BindEvent verwenden.

Konkret geht es mir aber nicht darum, wem welche Methode besser gefällt, sondern einfach darum, ob ich BindEvent "bedenkenlos" einsetzen kann oder ich mir damit später einen Haufen Ärger einhandel.

Ich wollte nicht noch einmal eine bereits geführte Diskussion auslösen (siehe viewtopic.php?f=16&t=30130&hilit=bindevent)

Gruß
Istvan42
MacOS Sonoma (M1), PureBasic 6.03 LTS (MacOS X - x64)
Benutzeravatar
HeX0R
Beiträge: 2954
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

Re: Klassische Eventschleife oder BindEvent/Callbacks?

Beitrag von HeX0R »

Istvan42 hat geschrieben:Ich wollte nicht noch einmal eine bereits geführte Diskussion auslösen (siehe viewtopic.php?f=16&t=30130&hilit=bindevent)
Sondern?
Eigentlich steht doch dort schon alles Wissenswertes!

Was für einen "Ärger" sollte man sich damit denn einhandeln?
Istvan42
Beiträge: 16
Registriert: 15.12.2019 16:59
Computerausstattung: MacOS Sonoma (M1), PureBasic 6.03 LTS (MacOS X - x64)

Re: Klassische Eventschleife oder BindEvent/Callbacks?

Beitrag von Istvan42 »

Was für einen "Ärger" sollte man sich damit denn einhandeln?
Genau das ist ja die Frage. Wenn es keine Nachteile hat, dann bin ich ja zufrieden ;-)
MacOS Sonoma (M1), PureBasic 6.03 LTS (MacOS X - x64)
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Klassische Eventschleife oder BindEvent/Callbacks?

Beitrag von NicTheQuick »

Für größere Projekte würde ich BindEvent auf jeden Fall empfehlen. Das hilft auch die Events für die einzelnen Fenster an der Stelle zu kapseln, wo man sie auch erzeugt. So kann man jedem Dialog und jedem Unterfenster eine Include geben, in der sich um alle Dinge für genau dieses Fenster gekümmert werden kann.

Die klassische Eventschleife nutze ich nur noch, wenn ich mir ein kleines Testprogramm zusammenbastel und ich bei vielen Events auf viele Daten zugreifen muss. Dann spare ich mir globale oder shared Variablen, oder Strukturen mit eben diesen Daten und SetWindowData() und Co.
Bild
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Klassische Eventschleife oder BindEvent/Callbacks?

Beitrag von mk-soft »

Verwende auch viel BindEvent. Sogar auch in Verbindung mit VirtualTables
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
ST4242
Beiträge: 42
Registriert: 29.10.2011 16:54

Re: Klassische Eventschleife oder BindEvent/Callbacks?

Beitrag von ST4242 »

Hallo,

ich persönlich hatte bevor es BINDEVENT gab eine Liste erstellt, in welcher alle Events eingetragen wurden mit Ansprungadresse auf die entsprechende Procedure - ähnlich wie BindEvent jetzt.

Der Vorteil Events wurden immer nur ausgelöst, wenn ich die Eventbearbeitung auch wollte.

Nachteil von BindEvent ist in meinen Augen, das immer sofort ausgeführt werden, egal was das Programm gerade macht.

Dies hatte bei mir zufolge, das innerhalb eines Drawings Blocks aufgrund eines Events ein zweiter Drawing Block gestartet wurde, was entsprechende Fehler nach sich zog. Dann mußte ich den 2. Block immer in einem getrennten Thread auslagern.

Langer Rede kurzer sinn. Im Regelfall funktioniert BindEvent sehr gut, leider muß mann aber auch aufpassen, welche Operationen innerhalb der Eventverarbeitung ausgeführt werden.


Gruß
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Klassische Eventschleife oder BindEvent/Callbacks?

Beitrag von mk-soft »

Das ist nicht ganz richtig...

Die mit BindEvent verbundenen Prozeduren werden erst mit dem Aufruf von WaitWindowEvent() nacheinander im Hauptprogramm verarbeitet.
Somit liegt die Verarbeitung der Prozeduren im Hauptprogramm.

Update
Die Reihenfolge ist etwas ungewöhnlich wenn man zum gleichen Objekt mehrere Prozeduren zuweist.
Kann man aber mit leben, wenn man es weiss.

Das zuletzt eingetragene BindEvent wird als erstes verarbeitet.

Code: Alles auswählen

;-TOP

Procedure DoEventButton()
  Debug "Begin 1: Bind Event Button..."
  Delay(500) ; Nur zum testen, nicht zu empflegen da diese das Event-Managment blockiert
  Debug "End 1: Bind Event Button..."
EndProcedure

Procedure DoEventButton2()
  Debug "Begin 2: Bind Event Button..."
  Delay(500) ; Nur zum testen, nicht zu empflegen da diese das Event-Managment blockiert
  Debug "End 2: Bind Event Button..."
EndProcedure

Procedure Main()
  If OpenWindow(0, 100, 100, 300, 200, "Test Event", #PB_Window_SystemMenu)
    ButtonGadget(0, 10, 10, 120, 30, "Do event")
    
    BindGadgetEvent(0, @DoEventButton())
    BindGadgetEvent(0, @DoEventButton2())
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Break
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0
              Debug "Main Event Button..."
          EndSelect
          
      EndSelect
      
    ForEver 
  EndIf
EndProcedure : Main()
P.S.
Somit kann man in der Event Prozedur auch den aktuellen Status vom Event abfragen.
EventWindow, EventGadget, EventType, etc

Code: Alles auswählen

;-TOP

Procedure DoEventString()
  Protected r1.s = " - "
  Debug "Bind Event String..."
  Select EventType()
    Case #PB_EventType_Focus : r1 + "#PB_EventType_Focus"
    Case #PB_EventType_LostFocus : r1 + "#PB_EventType_LostFocus"
    Case #PB_EventType_Change : r1 + "#PB_EventType_Change"
      
  EndSelect
  Debug r1
EndProcedure

Procedure Main()
  If OpenWindow(0, 100, 100, 300, 200, "Test Event", #PB_Window_SystemMenu)
    StringGadget(0, 10, 10, 280, 30, "")
    
    BindGadgetEvent(0, @DoEventString())
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Break
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0
              ;
          EndSelect
          
      EndSelect
      
    ForEver 
  EndIf
EndProcedure : Main()
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Antworten