GUI responsiveness or Event handling

Just starting out? Need help? Post your questions and find answers here.
User avatar
Erolcum
User
User
Posts: 51
Joined: Fri Jun 07, 2024 10:45 am
Location: Turkiye
Contact:

GUI responsiveness or Event handling

Post by Erolcum »

I write an article for beginners like me in my blog. Codes show two solutions to make gui responsive when program enters a long delayed procedure. May an experienced programmer show another solution by using a thread ? if possible :lol:
I simplified the codes from @Axolotl
my article https://erolcum-blogspot-com.translate ... r_pto=wapp

// Moved from "Tricks und Tipps" to "Coding Questions" (Kiffi)
You may visit my new Purebasic blog here..
:arrow: https://erolcum-github-io.translate.goo ... r_pto=wapp
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GUI responsiveness or Event handling

Post by infratec »

I personally always got a horror when I see a procedure inside of the normal code flow.

And ... it is very bad to use more then one event loop.
You can always loose events for the other loop.
In windows it is more or less possible to access the GUI stuff from a thread (SetGadgetText())
but in the other OSs this will fail definately.
You should always do such things in the main event loop via PostEvent().

And you did not use EnableExplicit. This can result in long debugging sessions.

Maybe when I later have a bit more time, I will modify the code how I would do it.
User avatar
Erolcum
User
User
Posts: 51
Joined: Fri Jun 07, 2024 10:45 am
Location: Turkiye
Contact:

Re: GUI responsiveness or Event handling

Post by Erolcum »

Yes you are absolutely right about nested procedures. I would really like to see your solution when it becomes available. Thanks @infratec
You may visit my new Purebasic blog here..
:arrow: https://erolcum-github-io.translate.goo ... r_pto=wapp
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GUI responsiveness or Event handling

Post by infratec »

Code: Select all

Case #PB_Event_CloseWindow    
      ApplicationQuit = #True 
      End
The End makes no sense :wink:
And it makes 'cleaning up' impossible.
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GUI responsiveness or Event handling

Post by infratec »

I hope everything what you want is included:

Code: Select all

EnableExplicit

CompilerIf Not #PB_Compiler_Thread
  CompilerError "Enable thread safe in compiler options!"
CompilerEndIf

#WINDOW_Main = 0
#WINDOW_Main_Flags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
#LOOP_MaxLoops        = 200 
#LOOP_SlowDownDelay   =  100

Enumeration Gadget 
  #GADGET_btnStart 
  #GADGET_btnStop 
  #GADGET_chkTest
  #GADGET_txtLoopOutput 
  #GADGET_lbTrace 
EndEnumeration 

Enumeration OwnEvent #PB_Event_FirstCustomValue
  #OwnEvent_ThreadStarted
  #OwnEvent_SetGadgetText
  #OwnEvent_ThreadFinished
EndEnumeration


Structure Parameter_Structure
  Thread.i
  Exit.i
EndStructure


Macro Trace(MessageText) 
  AddGadgetItem(#GADGET_lbTrace, -1, MessageText) 
  SetGadgetState(#GADGET_lbTrace, CountGadgetItems(#GADGET_lbTrace) -1) 
EndMacro 




Procedure Test_LongLoop(*Parameter.Parameter_Structure)
  
  Protected index.i, *msg
  
  
  PostEvent(#OwnEvent_ThreadStarted)
  
  For index = 0 To #LOOP_MaxLoops
    
    If *Parameter\Exit
      Break
    EndIf
    
    Delay(#LOOP_SlowDownDelay)  ; spend some time with nothing
    
    *msg = UTF8(" Item " + Str(index) + "/" + Str(#LOOP_MaxLoops) + " | Checkbox.State == " + GetGadgetState(#GADGET_chkTest))
    PostEvent(#OwnEvent_SetGadgetText, #WINDOW_Main, #GADGET_txtLoopOutput, 0, *msg)
    
  Next index
  
  *msg = UTF8("Loop finished (reached MaxLoops == " + Str(index) + ")")
  PostEvent(#OwnEvent_ThreadFinished, #WINDOW_Main, #GADGET_lbTrace, 0, *msg)
  
EndProcedure 



Define.i Event, ApplicationQuit, Exit
Define *msg
Define Parameter.Parameter_Structure


OpenWindow(#WINDOW_Main, 0, 0, 400, 320, "Event handling example...", #WINDOW_Main_Flags)
StickyWindow(#WINDOW_Main, 1)  ; show test app always above the PB_IDE
ButtonGadget(#GADGET_btnStart,  8, 4, 192, 32, "Start Looping")
ButtonGadget(#GADGET_btnStop, 200, 4, 192, 32, "Stop Looping")
DisableGadget(#GADGET_btnStop, #True)
CheckBoxGadget(#GADGET_chkTest, 8, 40, 384, 24, "Check me -- (see the event handling while the loop is running)") 
TextGadget(#GADGET_txtLoopOutput, 8, 72, 384, 20, "Loop is stopped.") 
SetGadgetColor(#GADGET_txtLoopOutput, #PB_Gadget_BackColor, GetSysColor_(#COLOR_INFOBK)) 
ListViewGadget(#GADGET_lbTrace, 8, 104, 384, 208, $4000)  ; #LBS_NOSEL == 0x4000 


Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #OwnEvent_ThreadStarted
      DisableGadget(#GADGET_btnStart, #True)
      DisableGadget(#GADGET_btnStop, #False)
      SetGadgetText(#GADGET_txtLoopOutput, "Loop is running")
      
    Case #OwnEvent_SetGadgetText
      *msg = EventData()
      SetGadgetText(EventGadget(), PeekS(*msg, -1, #PB_UTF8))
      FreeMemory(*msg)
      
    Case #OwnEvent_ThreadFinished
      DisableGadget(#GADGET_btnStart, #False)
      DisableGadget(#GADGET_btnStop, #True)
      *msg = EventData()
      If *msg
        Trace(PeekS(*msg, -1, #PB_UTF8))
        FreeMemory(*msg)
      EndIf
      SetGadgetText(#GADGET_txtLoopOutput, "Loop stopped.")
      If ApplicationQuit
        Exit = #True
      EndIf
      
    Case #PB_Event_MoveWindow
      Trace("  New Window Pos == " + WindowX(#WINDOW_Main) + ", " +WindowY(#WINDOW_Main))
      
    Case #PB_Event_CloseWindow
      ApplicationQuit = #True
      If IsThread(Parameter\Thread)
        Parameter\Exit = #True
      Else
        PostEvent(#OwnEvent_ThreadFinished)
      EndIf
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #GADGET_btnStart
          ClearGadgetItems(#GADGET_lbTrace) 
          Parameter\Exit = #False
          Parameter\Thread = CreateThread(@Test_LongLoop(), @Parameter)
          
        Case #GADGET_btnStop
          If IsThread(Parameter\Thread)
            Parameter\Exit = #True
          EndIf
          
        Case #GADGET_chkTest                         
          Trace("Gadget = #GADGET_chkTest == " + GetGadgetState(#GADGET_chkTest)) 
          
      EndSelect
  EndSelect 
  
Until Exit
This code should work an all OSs.
User avatar
Erolcum
User
User
Posts: 51
Joined: Fri Jun 07, 2024 10:45 am
Location: Turkiye
Contact:

Re: GUI responsiveness or Event handling

Post by Erolcum »

Thank you very much for your quick and excellent answer. You really make purebasic sing a song that you want :shock:
It will take some time to digest the codes you wrote.
You may visit my new Purebasic blog here..
:arrow: https://erolcum-github-io.translate.goo ... r_pto=wapp
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GUI responsiveness or Event handling

Post by infratec »

Ups ...

Code: Select all

GetSysColor_(#COLOR_INFOBK)
Is not cross platform.
And ... you can not compile it with the PB demo version.

For a beginner tutorial you should only use examples which can be compiled with the demo version.
User avatar
Erolcum
User
User
Posts: 51
Joined: Fri Jun 07, 2024 10:45 am
Location: Turkiye
Contact:

Re: GUI responsiveness or Event handling

Post by Erolcum »

ok. I will place it correctly in my blog. Code comes from another forum user :P
You may visit my new Purebasic blog here..
:arrow: https://erolcum-github-io.translate.goo ... r_pto=wapp
User avatar
Erolcum
User
User
Posts: 51
Joined: Fri Jun 07, 2024 10:45 am
Location: Turkiye
Contact:

Re: GUI responsiveness or Event handling

Post by Erolcum »

OK. I corrected the issues in my blog. Thank you again @infratec.
You may visit my new Purebasic blog here..
:arrow: https://erolcum-github-io.translate.goo ... r_pto=wapp
Post Reply