Simple Gadget Animation mit PB520b2

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Bisonte
Beiträge: 2471
Registriert: 01.04.2007 20:18

Simple Gadget Animation mit PB520b2

Beitrag von Bisonte »

Hier mal ein Beispiel das die neuen BindEvent Befehle nutzt.
In Verbindung mit einem Timer lässt sich daraus eine Animation
auf einem Canvas realisieren, und das sogar ohne Unterbrechungen
wenn man z.B. das Fenster bewegt. Das was vorher nur mit Threads
oder komplizierten Verrenkungen möglich war...

Der linke Mausknopf im Canvas startet/stoppt die Animation...

Code: Alles auswählen

EnableExplicit

#Window = 0
#Gadget = 0
#Timer  = 1

Procedure DrawOnCanvas()
  
  Static Pos.f, Richtung
  
  If StartDrawing(CanvasOutput(#Gadget))
    
    DrawingMode(#PB_2DDrawing_Gradient)
    BackColor(#Blue):FrontColor(#Blue)
    GradientColor(Pos, RGB(199,199,255))
    LinearGradient(0,0,300,0)
    Box(0,0,300,60,0)
    DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_Transparent)
    DrawText(10,10,"Simple GadgetAnim",0)
    
    If Richtung = 0
      pos + 0.02
    Else
      pos - 0.02
    EndIf
    
    If pos => 1
      richtung = 1
    ElseIf pos <= 0
      richtung = 0 
    EndIf
    
    StopDrawing()
  EndIf

EndProcedure
Procedure ProgramQuit()
  End
EndProcedure
Procedure CanvasButton()
  
  Static Go
  
  If Go = 0 ; Jetzt wird gestartet
    AddWindowTimer(#Window, #Timer, 10) ; <- Erstellen des Timers (nach wieviel ms neu gezeichnet werden soll)
    BindEvent(#PB_Event_Timer, @DrawOnCanvas(), #Window, #Timer) ; <- Hiermit wird der Timer mit der Zeichnungsprozedur verknüpft)
    Go = 1  
  Else ; Und nun wirds gestoppt
    UnbindEvent(#PB_Event_Timer, @DrawOnCanvas(), #Window, #Timer) ; <- Das Event wieder lösen
    RemoveWindowTimer(#Window, #Timer) ; <- und weg mit dem Timer
    Go = 0  
  EndIf
  
EndProcedure

Define Event

OpenWindow(#Window, 300, 300, 300, 60, "Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)

BindEvent(#PB_Event_CloseWindow, @ProgramQuit()) ; Das Fenster schliessen geht an ProgramQuit()

CanvasGadget(#Gadget, 0, 0, 300, 60)

BindGadgetEvent(#Gadget, @CanvasButton(), #PB_EventType_LeftButtonDown) ; Linker Mausknopf an Canvas knebeln.

DrawOnCanvas() ; Einmal Zeichnen damit irgendetwas da ist

Repeat
  Event = WaitWindowEvent()
ForEver
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Lambda
Beiträge: 526
Registriert: 16.06.2011 14:38

Re: Simple Gadget Animation mit PB520b2

Beitrag von Lambda »

Mit PostEvent() aus einem Thread heraus sind auch kollisionsfreie Updates möglich.
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Simple Gadget Animation mit PB520b2

Beitrag von RSBasic »

Cool, danke für dein Beispielcode mit dem Binden. :allright:
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Bisonte
Beiträge: 2471
Registriert: 01.04.2007 20:18

Re: Simple Gadget Animation mit PB520b2

Beitrag von Bisonte »

Alexi hat geschrieben:Mit PostEvent() aus einem Thread heraus sind auch kollisionsfreie Updates möglich.
Bisonte hat geschrieben:... vorher nur mit Threads oder komplizierten Verrenkungen möglich war...
nicht gelesen ? :mrgreen:
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Simple Gadget Animation mit PB520b2

Beitrag von STARGÅTE »

Danke für das Beispiel.
Dieser neue BindGadgetEvent()-Befehl ist also gerade für ein CustomGadget geeignet.

Sehr cool, wenn ich Zeit finde, werde ich meine Includes auf 5.20 umschreiben, denn das erleichtert ja schon die Benutzung von CustomGadgets.

Frage dazu:
Kann man an die Callbacks auch einen Parameter übergeben?
Bzw. kann man innerhalb des Callbacks auch auf EventType() zugreifen?
Wie ist die Reihenfolge bei der Abarbeitung der Callbacks? Scheinbar verdreht?

Code: Alles auswählen

OpenWindow(1, 300, 300, 300, 60, "Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)

Procedure A()
	Debug 1
EndProcedure
Procedure B()
	Debug 2
EndProcedure
Procedure C()
	Debug 3
EndProcedure

BindEvent(#PB_Event_CloseWindow, @A())
BindEvent(#PB_Event_CloseWindow, @B())
BindEvent(#PB_Event_CloseWindow, @C())

Repeat
  WaitWindowEvent()
ForEver
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Bisonte
Beiträge: 2471
Registriert: 01.04.2007 20:18

Re: Simple Gadget Animation mit PB520b2

Beitrag von Bisonte »

verdreht würd ich nicht sagen. Es hangelt sich halt von Callback zu Callback, in der Reihenfolge : First In - Last Out.
so wie es die WindowsCallbacks per Result = SetWindowLongPtr_(hWnd, #GWLP_WNDPROC, *ProcedureName) auch tun...
es wird ja jedesmal der "DefaultProc" mitgegeben, damit dieser am Ende des selbsterstellten wieder aufgerufen werden kann.

zum Eventtype :
Wenn man BindGadget() ohne Angabe des Eventtypes macht (ist ja optional) dann kann man im Callback mit EventType() arbeiten...
in meinem Beispiel oben z.B. ändere den Aufruf von BindGadget und die Prozedur CanvasButton()

Code: Alles auswählen

Procedure CanvasButton()
 
  Static Go
  
  If EventType() = #PB_EventType_LeftButtonDown
    
    If Go = 0 ; Jetzt wird gestartet
      AddWindowTimer(#Window, #Timer, 10) ; <- Erstellen des Timers (nach wieviel ms neu gezeichnet werden soll)
      BindEvent(#PB_Event_Timer, @DrawOnCanvas(), #Window, #Timer) ; <- Hiermit wird der Timer mit der Zeichnungsprozedur verknüpft)
      Go = 1 
    Else ; Und nun wirds gestoppt
      UnbindEvent(#PB_Event_Timer, @DrawOnCanvas(), #Window, #Timer) ; <- Das Event wieder lösen
      RemoveWindowTimer(#Window, #Timer) ; <- und weg mit dem Timer
      Go = 0 
    EndIf
    
  EndIf
  If EventType() = #PB_EventType_RightButtonDown
    MessageRequester("Hey","Ich sagte Linker Knopf")
  EndIf
  
EndProcedure

BindGadgetEvent(#Gadget, @CanvasButton()) ; Alle Eventtypes zum Canvas.
Allerdings sehe ich keinen Weg, dem Callback irgendetwas an Daten mitzugeben, es sei denn man reserviert sich Speicher
und hängt ihn an das Gadget ran (SetGadgetData oder SetProp_()) und liest es innerhalb des Callbacks wieder aus.

Edit: Witzigerweise stoppt nichtmal ein MessageRequester die Abbarbeitung des Timers :mrgreen:
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | 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: Simple Gadget Animation mit PB520b2

Beitrag von ts-soft »

Parameter: Nein
Alles was in einem normalen EventLoop ankommt, kommt auch in der Procedure an und läßt sich
genauso abfragen, also WindowEvent(), GadgetEvent(), EventType(), MenuEvent() usw.
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
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Simple Gadget Animation mit PB520b2

Beitrag von STARGÅTE »

Bisonte hat geschrieben:Edit: Witzigerweise stoppt nichtmal ein MessageRequester die Abbarbeitung des Timers :mrgreen:
Trotzdem werden die gebundenden Events nicht paralell abgearbeitet:

Code: Alles auswählen

OpenWindow(1, 300, 300, 300, 60, "Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)

Procedure A()
	Delay(1000)
   Debug 1
EndProcedure
Procedure B()
	Delay(1000)
   Debug 2
EndProcedure
Procedure C()
	Delay(1000)
   Debug 3
EndProcedure

BindEvent(#PB_Event_CloseWindow, @A())
BindEvent(#PB_Event_CloseWindow, @B())
BindEvent(#PB_Event_CloseWindow, @C())

Repeat
  WaitWindowEvent()
ForEver
Das Programm friert also solange bei WaitWindowEvent() ein, wie alle gebundenden Events zur abarbeitung brauchen.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten