Ereignisschleife

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
AnonymousForAll
Beiträge: 13
Registriert: 28.04.2017 11:21
Wohnort: Magdeburg

Ereignisschleife

Beitrag 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
PW für alle: 4n0nym0us
Andesdaf
Moderator
Beiträge: 2658
Registriert: 15.06.2008 18:22
Wohnort: Dresden

Re: Ereignisschleife

Beitrag 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.
Win11 x64 | PB 6.00 (x64)
Benutzeravatar
AnonymousForAll
Beiträge: 13
Registriert: 28.04.2017 11:21
Wohnort: Magdeburg

Re: Ereignisschleife

Beitrag 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.
PW für alle: 4n0nym0us
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Ereignisschleife

Beitrag 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 ;)
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Ereignisschleife

Beitrag 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.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Ereignisschleife

Beitrag 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.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Ereignisschleife

Beitrag 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
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
HolgerRo
Beiträge: 1
Registriert: 13.07.2017 23:23

Re: Ereignisschleife

Beitrag 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]
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Ereignisschleife

Beitrag 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
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Kurzer
Beiträge: 1614
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: Ereignisschleife

Beitrag 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
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2023: 56 Jahre.
Antworten