Seite 1 von 1

Ereignisschleife

Verfasst: 28.04.2017 11:35
von AnonymousForAll
Hallo Freunde

Wie baut ihr bezugsweise euere Ereignisschleife auf? Ich möchte gerne eine perfekte Event Schleife bauen und möglichst zukünftige Fehler vermeiden.

Könnt ihr mir Beispiele nennen die ich als Vorlage übernehmen kann?

Danke Freunde

Re: Ereignisschleife

Verfasst: 28.04.2017 11:54
von Andesdaf
Das kommt auch ein bisschen darauf an, wie umfangreich das Ganze werden soll.

Für kleine Projekte tut es sicherlich die Eventschleife, die in der Hilfe unter WaitWindowEvent
beispielhaft skizziert ist, ansonsten kannst du auch den BindEvent-Mechanismus nutzen.

Re: Ereignisschleife

Verfasst: 28.04.2017 12:26
von AnonymousForAll
Hallo Andesdaf

Ich möchte möglichst viele Gadgets abfragen und viele Fenster Events wie SIZE und MOVE. Es soll trotz vieler Gadget Abfragen noch übersichtlich sein.

Re: Ereignisschleife

Verfasst: 28.04.2017 13:12
von Bisonte
Mit BindEvent, BindGadgetEvent, BindMenuEvent kann man fast die gesamte Ereignisschleife "entmüllen"...

Es kommt wirklich darauf an, was genau man machen möchte. So eine universelle überall einsetzbare und dann noch übersichtiliche
ist meines Wissens beinahe unmöglich ;)

Re: Ereignisschleife

Verfasst: 28.04.2017 15:02
von ts-soft
Kein Code ohne Ereignis im Eventloop! Notfalls wird ein Ereignis "erfunden" (Timer).
Alle Ereignisse möglichst bis zum Ende auflösen, also z.B. EventGadget, EventType usw.
Möglichst nur einen Abfragetyp verwenden, also entweder Select/Case/EndSelect oder If/ElseIf/Else/EndIf.

Alle Echtzeitereignisse, also Move, Size usw. möglichst mit BindEvent in ein Callback packen.

Dies nur als Richtschnur, ansonsten ist so eine Schleife meist sehr Individuell.

Re: Ereignisschleife

Verfasst: 28.04.2017 15:31
von RSBasic
Wie die anderen bereits geschrieben haben, ist es je nach Anwendungsfall unterschiedlich und natürlich individuell.
Ich verwende in neueren Projekten ausschließlich die BindEvent-Funktionen, damit nicht alle Events in einer einzigen Schleife untereinander durchgearbeitet werden. Das ist meiner Meinung nach zu unübersichtlich.
Ich lagere sie gerne in separaten Prozeduren ab und dank BindEvent brauche ich in der Hauptschleife nichts mehr schreiben außer: Repeat : WaitWindowEvent() : ForEver

Ansonsten kannst du deine Event-Schleife auch so aufbauen:

Code: Alles auswählen

EnableExplicit

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Menu
        Select EventMenu()
          Case 1
            
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            
        EndSelect
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf
Aber ich würde dir BindEvent empfehlen.

Re: Ereignisschleife

Verfasst: 28.04.2017 17:14
von mk-soft
Verwende auch BindEvent in Verbindung mit Select...

Wichtig ist es das im Programm immer nur ein WaitWindowEvent() gibt. Kapseln vom Hauptprogramm ist auch von Vorteil.

Zum testen habe ich immer ein Template bereit...
Auch wenn es jeder anders macht, hier eine Beispiel. Hat aber alles was erforderlich ist.

Code: Alles auswählen

;-TOP

; Constant
Enumeration ;Window
  #Main
EndEnumeration

Enumeration ; Menu
  #Main_Menu
EndEnumeration

Enumeration ; MenuItems
  #Main_MenuExitApplication
EndEnumeration
  
Enumeration ; Gadgets
  #Main_Splitter
  #Main_List
  #Main_Edit
EndEnumeration

Enumeration ; Statusbar
  #Main_Status
EndEnumeration

; Global Variable
Global ExitApplication

; ***************************************************************************************

; Functions
Procedure UpdateWindow()
  
  Protected x, y, dx, dy, menu, status
  
  menu = MenuHeight()
  If IsStatusBar(#Main_Status)
    status = StatusBarHeight(#Main_Status)
  Else
    status = 0
  EndIf
  x = 0
  y = 0
  dx = WindowWidth(#Main)
  dy = WindowHeight(#Main) - menu - status
  ResizeGadget(#Main_Splitter, x, y, dx, dy)
  
EndProcedure

; ***************************************************************************************

Procedure MyLogging(Text.s)
  
  Protected temp.s, c
  
  temp = FormatDate("%HH.%II.%SS - ", Date())
  temp + Text
  AddGadgetItem(#Main_List, -1, temp)
  c = CountGadgetItems(#Main_List)
  If c > 1000
    RemoveGadgetItem(#Main_List, 0)
    c - 1
  EndIf
  c - 1
  SetGadgetState(#Main_List, c)
  SetGadgetState(#Main_List, -1)
  
EndProcedure

Global MutexLogs = CreateMutex()

Macro Logging(Text)
  LockMutex(MutexLogs) : MyLogging(Text) : UnlockMutex(MutexLogs)
EndMacro

; ***************************************************************************************

;- Events

Procedure MyEventMenu()
  Select EventMenu()
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS   
      Case #PB_Menu_About
        MessageRequester("Info", "Basis v1.0")
        
      Case #PB_Menu_Preferences
        
      Case #PB_Menu_Quit
        ExitApplication = #True
        
    CompilerEndIf
      
    Case #Main_MenuExitApplication
      ExitApplication = #True
      
  EndSelect
EndProcedure

Procedure MyEventGadget()
  Select EventGadget()
    Case #Main_List
      
    Case #Main_Edit
      
  EndSelect
EndProcedure

Procedure MyEventSizeWindow()
  Select EventWindow()
    Case #Main
      UpdateWindow()
      
  EndSelect
EndProcedure

Procedure MyEventCloseWindow()
  Select EventWindow()
    Case #Main
      ExitApplication = #True
      
  EndSelect
EndProcedure

;- Main

Procedure Main()
  
  Protected event, style, dx, dy
  
  style = #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget
  dx = 800
  dy = 600
  
  If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, dx, dy, "Main", style)
    
    ; Menu
    CreateMenu(#Main_Menu, WindowID(#Main))
    MenuTitle("Ablage")
    MenuItem(#Main_MenuExitApplication, "Be&enden")
    
    ; Gadgets
    ListViewGadget(#Main_List, 0, 0, 0, 0)
    EditorGadget(#Main_Edit, 0, 0, 0, 0)
    SplitterGadget(#Main_Splitter, 0, 0, dx ,dy, #Main_List, #Main_Edit)
    SetGadgetState(#Main_Splitter, dy * 2 / 3)
    
    ; Statusbar
    CreateStatusBar(#Main_Status, WindowID(#Main))
    AddStatusBarField(#PB_Ignore)
    
    ; For Mac
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
      ; Enable Fullscreen
      Protected NewCollectionBehaviour
      NewCollectionBehaviour = CocoaMessage(0, WindowID(#Main), "collectionBehavior") | $80
      CocoaMessage(0, WindowID(#Main), "setCollectionBehavior:", NewCollectionBehaviour)
      ; Mac default menu
      If Not IsMenu(#Main_Menu)
        CreateMenu(#Main_Menu, WindowID(#Main))
      EndIf
      MenuItem(#PB_Menu_About, "")
      MenuItem(#PB_Menu_Preferences, "")
    CompilerEndIf
    
    ; Events binden
    BindEvent(#PB_Event_Menu, @MyEventMenu())
    BindEvent(#PB_Event_Gadget, @MyEventGadget())
    BindEvent(#PB_Event_SizeWindow, @MyEventSizeWindow())
    BindEvent(#PB_Event_CloseWindow, @MyEventCloseWindow())
    
    UpdateWindow()
    
    Logging("Programm gestartet")
    ; Main Loop
    Repeat
      event = WaitWindowEvent()
      Select event
          ; Andere Events
          
      EndSelect
      
    Until ExitApplication
    
  EndIf
  
EndProcedure : Main()

End

;- BOTTOM
Für größere Projekte lasse ich mir alle erforderlichen Programmcodes mit mein Tool automatisch erstellen.
Solltest aber es dir erst anschauen wenn du mit der PB Event-Verarbeitung klar kommst

Re: Ereignisschleife

Verfasst: 14.07.2017 23:27
von HolgerRo
Moin,
ich habe auch probleme mit den Schleifen.
wie bekomme ich das hin, das Programm mit nach dem errsten Endselect nicht stehen bleibt.
Ich versuche mich nach 35 Jahren GWBasic und Qbasic jetzt in Purebasic einzuarbeiten.
Danke für Verständis und evt Hilfe.

Code: Alles auswählen


Case 82
           LoadFont(501,"ITC Zapf Chancery SWA",18) : SetGadgetFont(#PB_Default,FontID(501))
           TextGadget(501,20,50,500,30,"Bestattungsinstitut - Manager         ") 
           TextGadget(502,20,80,500,30,"Nutzer Daten                          ")
           LoadFont(502,"Bookman Old Style",14) 
           SetGadgetFont(#PB_Default,FontID(502))
           ButtonGadget(505,320,905,320,30,"Speichern")
           
         OpenFile(0,"C:\BIMHR\Install\Nutzer.DAT",#PB_Ascii)
         B = 100 : For A = 1 To 25 : C = A + 100 : B = B + 30
          A$ = ReadString(0) :  B$ = Left(A$,29) : C$ = Mid(A$,30,30)
           
         If Left(B$,4) <> "    "
           StringGadget(A,320,B,320,30,C$) 
           TextGadget(C,50,B,270,30,B$)
         Else
           StringGadget(A,320,B,0,30,C$) 
           TextGadget(C,50,B,270,30,"       - -")
         EndIf
       Next a
       
       B = 100 : For A = 26 To 50 : B = B + 30 : C = A + 100
        A$ = ReadString(0) :  B$ = Left(A$,29) : C$ = Mid(A$,30,30)          
           If Left(B$,4) <> "    "
           StringGadget(A,920,B,320,30,C$)
           TextGadget(C,650,B,270,30,B$) 
         Else
           StringGadget(A,920,B,0,30,C$) 
           TextGadget(C,650,B,270,30,"       - -")
           EndIf
         Next a
         CloseFile(0)
         
                     
           Repeat
             Select WindowEvent()
              Case #PB_Event_CloseWindow
              End
              Case #PB_Event_Gadget
               If EventGadget() = 505
                 
                OpenFile(0,"C:\BIMHR\INSTALL\Nutzer.DAT",#PB_Ascii)           
                 For A = 1 To 50 : C = A + 100 : B = B + 30
                  C$ = GetGadgetText(A) : SetGadgetText(A,C$)
                  B$ = GetGadgetText(C) : SetGadgetText(C,B$)                
                  WriteString(0,Left(B$,35)) : WriteStringN(0,C$)
                Next
                CloseFile(0)
                TextGadget(510,920,905,300,30,"Daten gespeichert") 
              Else
                TextGadget(510,920,905,300,30,"Daten nicht gespeichert")
             
                
              EndIf
             EndSelect
           Until Quit = 1
                               
         Case 83
           LoadFont(501,"ITC Zapf Chancery SWA",18) 
           SetGadgetFont(#PB_Default,FontID(501))
           TextGadget(501,20,50,500,30,"Bestattungsinstitut - Manager         ") 
           TextGadget(502,20,80,500,30,"Programm Daten                          ")
           LoadFont(502,"Bookman Old Style",14) 
           SetGadgetFont(#PB_Default,FontID(502))
           ButtonGadget(505,320,905,320,30,"Speichern")
             
         OpenFile(0,"C:\BIMHR\INSTALL\Programm.DAT",#PB_Ascii)
         B = 100 : For A = 1 To 25 : C = A + 100 : B = B + 30
        
         A$ = ReadString(0) :  B$ = Left(A$,35) : C$ = Mid(A$,36,25) : D$ = Mid(A$,61,25) : E$ = Mid(A$,86,25)  
         If Left(B$,4) <> "    "
           StringGadget(A,320,B,320,30,C$) 
           TextGadget(C,50,B,270,30,B$)
         Else
           StringGadget(A,320,B,0,30,C$) 
           TextGadget(C,50,B,270,30,"       - -")
         EndIf
       Next a
       
       CloseFile(0)
           B = 100 : For A = 26 To 50 : B = B + 30 : C = A + 100
           TextGadget(A,920,B,320,30," ")
           TextGadget(C,650,B,270,30," ") 
           Next a
                     
           Repeat
             Select WindowEvent()
               Case #PB_Event_CloseWindow
              End
             Case #PB_Event_Gadget
               If EventGadget() = 505
                 
               OpenFile(0,"C:\BIMHR\INSTALL\Programm.DAT",#PB_Ascii)         
                For A = 1 To 25 : C = A + 100 : B = B + 30
                  C$ = GetGadgetText(A) : SetGadgetText(A,C$)
                  B$ = GetGadgetText(C) : SetGadgetText(C,B$)                
                  WriteString(0,Left(B$,35)) : WriteString(0,Left(C$,25)): WriteString(0,Left(D$,25)): WriteStringN(0,Left(E$,25))
                Next
                CloseFile(0)
                TextGadget(510,920,905,300,30,"Daten gespeichert") 
              Else
                TextGadget(510,920,905,300,30,"Daten nicht gespeichert")
              
            EndIf 
           EndSelect 
           
         Until Quit = 1
[/color]

Re: Ereignisschleife

Verfasst: 15.07.2017 00:31
von ts-soft
@HolgerRo

Erstmal die GUI usw. von der Eventschleife trennen. Ein Windows-Programm ist Ereignisgesteuert und nicht wie in Deinem Beispiel.
Außerdem wären etwas aussagekräftigere Variablen sehr sinnvoll, kein A oder B. Die Nutzung von Proceduren wäre auch sinnvoll.

Es sollte nur eine Ereignisschleife geben und nicht mehrere wie in Deinem Code. Normalerweise nimmt man auch WaitWindowEvent() und nicht
WindowEvent() was nur in seltenen Fällen sinnvoll ist.

Lies Dir nochmals diesen Beitrag durch, sowie guck Dir Beispiele in der Hilfe an und vergiss am besten alles, was Du da vor 35 Jahren mal gelernt hast,
weil da gab es noch keine ereignisgesteuerte Windows-Programme. Du solltest also komplett Umdenken, was meist schwerer ist, als ganz neu
anzufangen.

Mit dem Stil Deines Beispiels, wird das nichts werden. Hier haste zwar ein paar neue PureBasic-Funktionen eingefügt, aber in einem nicht sehr sinnvollem
Codeaufbau. Das wird wohl nicht reichen um daraus ein ereignisorientiertes Programm zu erzeugen.

Gruß
Thomas

Re: Ereignisschleife

Verfasst: 15.07.2017 23:14
von Kurzer
AnonymousForAll hat geschrieben:Wie baut ihr bezugsweise euere Ereignisschleife auf? Ich möchte gerne eine perfekte Event Schleife bauen und möglichst zukünftige Fehler vermeiden.
Ich schließe mich der Bind*Event() Fraktion an und Danke Fred noch immer, dass er diese Art von Eventmanagement nun nativ in PB eingebaut hat (leider erst nachdem ich mir ein komplettes Event-Management system selbst geschrieben habe... grummel).

Mittlerweile arbeite ich mit vorgefertigten, modularen Projekt-Templates, die mir ein komplettes Programmgerüst für neue Projekte anbieten inkl. Routinen für das Speichern von Settings, Fensterpositionen usw. sowie dem Gadgetmanagement in den einzelnen Fenstern. So muss ich mich meist nur noch um die restliche Programmfunktionalität kümmern.

Ich nutze dabei eine minimale Eventschleife, die eigentlich nur auf das Schließen des Hauptfensters reagiert.

Code: Alles auswählen

		;*************************************************************************
		;* Eventloop
		;*************************************************************************
		Repeat
			stApplication\iEvent = WaitWindowEvent()
		Until stApplication\iQuit = #True
Den Rest decke ich komplett mit Bindevent ab.

Code: Alles auswählen

Procedure   Main_RegisterEvents()
	; +-----------------------------------------------------------------
	; |Description  : Ordnet den Gadgets, Menüs usw. die Eventprozeduren zu
	; |Arguments    : -
	; |Results      : -
	; |Remarks      : -
	; +-----------------------------------------------------------------
	BindMenuEvent(#Menu_Window_Main, #Menu_Window_Main_Open, @Event_Main_Menu_Open())
	BindMenuEvent(#Menu_Window_Main, #Menu_Window_Main_Settings, @Event_Main_Menu_Settings())
	BindMenuEvent(#Menu_Window_Main, #Toolbar_Window_Main_Open, @Event_Main_Menu_Open())
	
	BindGadgetEvent(Window_Main_Button_Exit, @Event_Main_Button_Exit(), #PB_EventType_LeftClick)
	
	BindEvent(#PB_Event_SizeWindow, @Event_Main_WindowHandler(), Window_Main)
	BindEvent(#PB_Event_MoveWindow, @Event_Main_WindowHandler(), Window_Main)
	BindEvent(#PB_Event_CloseWindow, @Event_Main_Button_Exit(), Window_Main)
	
EndProcedure
Procedure   Main_UnregisterEvents()
	; +-----------------------------------------------------------------
	; |Description  : Hebt die Zuordnung der Eventprozeduren auf
	; |Arguments    : -
	; |Results      : -
	; |Remarks      : -
	; +-----------------------------------------------------------------
	UnbindMenuEvent(#Menu_Window_Main, #Menu_Window_Main_Open, @Event_Main_Menu_Open())
	UnbindMenuEvent(#Menu_Window_Main, #Menu_Window_Main_Settings, @Event_Main_Menu_Settings())
	UnbindMenuEvent(#Menu_Window_Main, #Toolbar_Window_Main_Open, @Event_Main_Menu_Open())
	
	UnbindGadgetEvent(Window_Main_Button_Exit, @Event_Main_Button_Exit(), #PB_EventType_LeftClick)
	
	UnbindEvent(#PB_Event_SizeWindow, @Event_Main_WindowHandler(), Window_Main)
	UnbindEvent(#PB_Event_MoveWindow, @Event_Main_WindowHandler(), Window_Main)
	UnbindEvent(#PB_Event_CloseWindow, @Event_Main_Button_Exit(), Window_Main)
	
EndProcedure