How to refresh?

Just starting out? Need help? Post your questions and find answers here.
platy
New User
New User
Posts: 6
Joined: Wed Jun 16, 2021 7:05 pm

How to refresh?

Post by platy »

Hi all,

I log messages to a listview gadget via AddItem(). When a time-consuming command immediately follows my log command (such as deleting a large dir tree via DeleteDirectory), the message(s) show up in the listview AFTER the time-consuming command finishes.

How do I get them to show up immediately BEFORE the time-consuming command runs?

Thanks for any suggestions!
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Re: How to refresh?

Post by GPI »

you must handle the windows-events

Code: Select all

while windowevent():wend
will do it, BUT it ignores all events!
platy
New User
New User
Posts: 6
Joined: Wed Jun 16, 2021 7:05 pm

Re: How to refresh?

Post by platy »

Oops, forgot to mention that my code runs in a callback proc (after a button click) so I cannot call WaitEvent/WaitWindowEvent in there ...
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: How to refresh?

Post by infratec »

For long running code you need a thread.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: How to refresh?

Post by RASHAD »

It will be very helpful if you posted a very simple exam.to show how you run your commands with windows callback
Egypt my love
platy
New User
New User
Posts: 6
Joined: Wed Jun 16, 2021 7:05 pm

Re: How to refresh?

Post by platy »

Like so:

Code: Select all

EnableExplicit

Enumeration Gadgets
  #CurWindow
  #ButtonStart
  #ListviewLog
EndEnumeration  

#DateTimeFormat = "%yyyy-%mm-%dd %hh:%ii:%ss" ; ISO 8601

Procedure LogMessage(Msg.s)
  AddGadgetItem(#ListviewLog, -1, FormatDate(#DateTimeFormat, Date()) + " " + Msg)
EndProcedure

Procedure ButtonClick()
  ClearGadgetItems(#ListviewLog)
  LogMessage("Process started.")
  ; now start a time consuming process here (in my case, deleting a huge dir tree)
  ; the log message only shows up upon completion of that process
EndProcedure  

Procedure OpenFormWindow()
  If OpenWindow(#CurWindow, #PB_Ignore, #PB_Ignore, 800, 600, "Issue Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
    ButtonGadget(#ButtonStart,   10, 10,  80,  25, "Start")
    ListViewGadget(#ListviewLog, 10, 40, 780, 550)
    BindGadgetEvent(#ButtonStart, @ButtonClick())
  EndIf  
EndProcedure

OpenFormWindow()

Define Event
Repeat
  Event = WaitWindowEvent()
  Select Event
    ; ...  
  EndSelect
Until Event = #PB_Event_CloseWindow
Marc56us
Addict
Addict
Posts: 1477
Joined: Sat Feb 08, 2014 3:26 pm

Re: How to refresh?

Post by Marc56us »

Example of a thread that updates the main interface (yes, you can, as long as the updated gadget is not accessed at the same time by another part of the program).
With this system, the interface is not blocked during the Deltree

Code: Select all

EnableExplicit

Enumeration Gadgets
    #CurWindow
    #ButtonStart
    #ListviewLog
EndEnumeration  

#DateTimeFormat = "%yyyy-%mm-%dd %hh:%ii:%ss" ; ISO 8601

Procedure LogMessage(Msg.s)
    AddGadgetItem(#ListviewLog, -1, FormatDate(#DateTimeFormat, Date()) + " " + Msg)
EndProcedure

; --- main task running in thread 
Procedure DeleteTree(*value)
    Protected i
    Repeat
        i + 1   
        ; --- Yes, you can update main GUI if no other task modify the gadget
        LogMessage("Hi " + Str(i))
        Delay(1000)
    ForEver
EndProcedure

Procedure ButtonClick()
    ClearGadgetItems(#ListviewLog)
    LogMessage("Process started.")
    ; now start a time consuming process here (in my case, deleting a huge dir tree)
    ; the log message only shows up upon completion of that process
    ; Main task
    CreateThread(@DeleteTree(), 1)
EndProcedure  

Procedure OpenFormWindow()
    If OpenWindow(#CurWindow, #PB_Ignore, #PB_Ignore, 800, 600, "Issue Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
        ButtonGadget(#ButtonStart,   10, 10,  80,  25, "Start")
        ListViewGadget(#ListviewLog, 10, 40, 780, 550)
        BindGadgetEvent(#ButtonStart, @ButtonClick())
    EndIf  
EndProcedure

OpenFormWindow()

Define Event
Repeat
    Event = WaitWindowEvent()
    Select Event
            ; ...  
    EndSelect
Until Event = #PB_Event_CloseWindow
But you can't show the state of DeleteDirectory() because it's au single command.

You can "pass the time" by making a fake progressbar (i.e update sec by sec)

Check [X] ThreadSafe in compiler option.

:wink:
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Re: How to refresh?

Post by GPI »

IMPORTANT. You should not call Gadget/Windows-Commands in Threads. It works on Windows, but not on other os.
Marc56us
Addict
Addict
Posts: 1477
Joined: Sat Feb 08, 2014 3:26 pm

Re: How to refresh?

Post by Marc56us »

GPI wrote: Thu Jun 17, 2021 6:14 pm IMPORTANT. You should not call Gadget/Windows-Commands in Threads. It works on Windows, but not on other os.
Tested on Linux Slackware with PB 5.73 LTS x64: Work fine :wink:
I don't have a mac, but knowing that they are based on *BSD it must also work, I think.

Maybe it was valid for the old versions of PB?

So far I never had any problem, but all my programs are still very "basic": I almost never use pointers for example and very rarely direct API calls
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to refresh?

Post by mk-soft »

On Linux work perhaps, but not stable ...
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
platy
New User
New User
Posts: 6
Joined: Wed Jun 16, 2021 7:05 pm

Re: How to refresh?

Post by platy »

@Marcus:

Hmm - not so sure about your solution. As it stands, it works flawlessly or so it seems. The moment I add a WaitThread(), it hangs.

However, if I remove the GUI calls it works with WaitThread().
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to refresh?

Post by mk-soft »

Solution with PostEvent ... Not the first :wink:

Update
- macOS don't like running thread ...

Code: Select all

EnableExplicit

Procedure AllocateString(Text.s)
  Protected *mem.String
  *mem = AllocateStructure(String)
  If *mem
    *mem\s = Text
  EndIf
  ProcedureReturn *mem
EndProcedure

Procedure.s FreeString(*Mem.String)
  Protected r1.s
  If *Mem
    r1 = *Mem\s
    FreeStructure(*Mem)
  EndIf
  ProcedureReturn r1
EndProcedure

; ----

Enumeration Gadgets
  #CurWindow
  #ButtonStart
  #ListviewLog
EndEnumeration  

#DateTimeFormat = "%yyyy-%mm-%dd %hh:%ii:%ss" ; ISO 8601

Enumeration CustomEvent #PB_Event_FirstCustomValue
  #MyEvent_LogMessage
EndEnumeration

Procedure DispatchLogMessage()
  AddGadgetItem(#ListviewLog, -1, FormatDate(#DateTimeFormat, Date()) + " " + FreeString(EventData()))
EndProcedure

BindEvent(#MyEvent_LogMessage, @DispatchLogMessage())

Procedure LogMessage(Msg.s)
  PostEvent(#MyEvent_LogMessage, 0, 0, 0, AllocateString(Msg))
EndProcedure

Global ExitThreads
; --- main task running in thread 
Procedure DeleteTree(*value)
  Protected i
  Repeat
    i + 1   
    ; --- Yes, you can update main GUI if no other task modify the gadget
    LogMessage("Hi " + Str(i))
    Delay(1000)
  Until ExitThreads
EndProcedure

Procedure ButtonClick()
  ClearGadgetItems(#ListviewLog)
  LogMessage("Process started.")
  ; now start a time consuming process here (in my case, deleting a huge dir tree)
  ; the log message only shows up upon completion of that process
  ; Main task
  CreateThread(@DeleteTree(), 1)
EndProcedure  

Procedure OpenFormWindow()
  If OpenWindow(#CurWindow, #PB_Ignore, #PB_Ignore, 800, 600, "Issue Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
    ButtonGadget(#ButtonStart,   10, 10,  80,  25, "Start")
    ListViewGadget(#ListviewLog, 10, 40, 780, 550)
    BindGadgetEvent(#ButtonStart, @ButtonClick())
  EndIf  
EndProcedure

OpenFormWindow()

Define Event
Repeat
  Event = WaitWindowEvent()
  Select Event
      ; ...  
  EndSelect
Until Event = #PB_Event_CloseWindow

ExitThreads = #True
Delay(2000)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: How to refresh?

Post by RASHAD »

Hi
Did not test it but I hope it will do the job

Code: Select all

EnableExplicit
Global start,startflag

Enumeration Gadgets
  #CurWindow
  #ButtonStart
  #ListviewLog
EndEnumeration  

#DateTimeFormat = "%yyyy-%mm-%dd %hh:%ii:%ss" ; ISO 8601

Procedure LogMessage(Msg.s)
  AddGadgetItem(#ListviewLog, -1, FormatDate(#DateTimeFormat, Date()) + " " + Msg)
EndProcedure

Procedure ButtonClick()
  ClearGadgetItems(#ListviewLog)
  LogMessage("Process started.")
  startflag = 1
  start = ElapsedMilliseconds()
  ; now start a time consuming process here (in my case, deleting a huge dir tree)
  ; the log message only shows up upon completion of that process
  startflag = 0
EndProcedure  

Procedure OpenFormWindow()
  If OpenWindow(#CurWindow, #PB_Ignore, #PB_Ignore, 800, 600, "Issue Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
    ButtonGadget(#ButtonStart,   10, 10,  80,  25, "Start")
    ListViewGadget(#ListviewLog, 10, 40, 780, 550)
    BindGadgetEvent(#ButtonStart, @ButtonClick())
    AddWindowTimer(#CurWindow,125,10)
  EndIf  
EndProcedure

OpenFormWindow()

Define Event
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit =1
      
    Case #PB_Event_Timer
      If startflag = 1
        LogMessage(Str(ElapsedMilliseconds()-start) +" % Completed")
      EndIf
    ; ...  
  EndSelect
Until Quit = 1

Egypt my love
Marc56us
Addict
Addict
Posts: 1477
Joined: Sat Feb 08, 2014 3:26 pm

Re: How to refresh?

Post by Marc56us »

As indicated in the help, WaitThread() completely STOPS the main part of the program (partly like Delay, which STOPS ALL the program). Avoid use this technic
To get information from a thread, use rather Rashad's solution (Flag) or mksoft's (PostEvent)
:wink:
platy
New User
New User
Posts: 6
Joined: Wed Jun 16, 2021 7:05 pm

Re: How to refresh?

Post by platy »

Thank you all for your contributions - much appreciated.
Post Reply