Progress Bar Threaded

Just starting out? Need help? Post your questions and find answers here.
benco5000
User
User
Posts: 13
Joined: Mon Mar 01, 2010 8:56 pm

Progress Bar Threaded

Post by benco5000 »

My progress bar does not update properly. I read on the blog that it needed to be threaded.
Not sure how to update the progress bar from the main window? Around lines 42 - 63
Chopped this down from another program so this example may be more complex than it needs to be.

TIA

Code: Select all

; ------------------------------------------------------------
;  progress bar example
; ------------------------------------------------------------
; ------------------------------------------------------------
;  variables
; ------------------------------------------------------------
Global eWaitWindow.i                                                            ;;
Global eType.i                                                                  ;;
Global gActiveGadget.i                                                          ;;

Global progressBarWindow.i = 0                                                  ;;
Global gProgressBarGadget.i = 0                                                 ;;
Global gProgressBarGadgetLevel.i = 50                                           ;;

Global gDoneYet.i = 0                                                           ;;

;------------------------------------------------------------
; init a main window
;------------------------------------------------------------
Global gWinMain = OpenWindow( #PB_Any, 0, 0, 480, 320,                          ;; create a window get windowID into mainWin
_                     "winMain",                                                ;; title
_                     #PB_Window_SystemMenu |                                   ;; has system menu
_                     #PB_Window_SizeGadget |                                   ;; allow resize
_                     #PB_Window_MinimizeGadget |                               ;; has minimize button
_                     #PB_Window_MaximizeGadget |                               ;; has maximize button
_                     #PB_Window_ScreenCentered)                                ;; center the screen

;------------------------------------------------------------
; two buttons
;------------------------------------------------------------
Global gBtnPrev = ButtonGadget(#PB_Any, 305, 10, 80, 24, "DEC")                 ;; DEC
Global gBtnNext = ButtonGadget(#PB_Any, 390, 10, 80, 24, "INC")                 ;; INC

;------------------------------------------------------------
; a field
;------------------------------------------------------------
Global gFieldValue = StringGadget(#PB_Any, 40, 40, 320, 24,"")                  ;; see the current value

;------------------------------------------------------------
; progress bar
;------------------------------------------------------------
Procedure progressBar(gDoneYet)                                                 ;; this will be threaded
  If OpenWindow(0, 0, 0, 320, 20, "Progress ...",                               ;; main window for progress bar
    _                                #PB_Window_SystemMenu |                    ;;
    _                                #PB_Window_ScreenCentered |                ;;
    _                                #PB_Window_Tool |                          ;;
    _                                #PB_Window_BorderLess)                     ;;
    
    gProgressBarGadget = ProgressBarGadget(#PB_Any,                             ;; progress bar
    _                                      0,0,320,20,0,100,                    ;;
    _                                      #PB_Window_WindowCentered)           ;;

    Repeat                                                                      ;; loop begin
      SetGadgetState(gProgressBarGadget, gProgressBarGadgetLevel)               ;; set the state
      Delay (250)                                                               ;; fast enough
    Until WaitWindowEvent()=#PB_Event_CloseWindow                               ;; close option
    
    ;; ********************************************************************************************************
    ;;  must process events here???
    ;;  how do I get the window to automatically update progress bar??
    ;; ********************************************************************************************************
  EndIf                                                                         ;; end main window of progressbar
EndProcedure                                                                    ;; end procedure for progressbar

Thread = CreateThread(@progressBar(), 0)                                        ;; start the procedure

;------------------------------------------------------------
; mouse navigation
;------------------------------------------------------------
Procedure MouseNavigationLeft()
  ;-----------------------------------------------------------
  ; [Left Mouse Button] clicked
  ; find which gadget and take action
  ;-----------------------------------------------------------
  If gWin_kb_MouseButtonLeft > -1 And _                                       ;; if mouse button is clicked
      EType = 0                                                               ;; mouseUp
    
    Select (gActiveGadget)                                                    ;; which gadget sent a left click
      
      ;-----------------------------------------------------------
      ; [Left Mouse] click on Prev card button
      ;-----------------------------------------------------------
    Case gBtnPrev                                                             ;; prev Button clicked
      If gProgressBarGadgetLevel > 1                                          ;; if level is not zero
        gProgressBarGadgetLevel = gProgressBarGadgetLevel - 10                ;; subtract 10
        SetGadgetText(gFieldValue, Str(gProgressBarGadgetLevel))              ;; show number in field
      EndIf                                                                   ;; end if prev button clicked
      
      
      ;-----------------------------------------------------------
      ; [Left Mouse] click on Next card button
      ;-----------------------------------------------------------
    Case gBtnNext                                                             ;; next Button clicked  
      If gProgressBarGadgetLevel < 100                                        ;; if level is not 100
        gProgressBarGadgetLevel = gProgressBarGadgetLevel + 10                ;; add 10
        SetGadgetText(gFieldValue, Str(gProgressBarGadgetLevel))              ;; show number in field
      EndIf                                                                   ;; end if next button clicked
    EndSelect                                                                 ;; end select gadget from left click
  EndIf                                                                       ;; end if mouse button clicked
EndProcedure                                                                  ;; end procedure mouse navigation left

;------------------------------------------------------------
; event loop
;------------------------------------------------------------
Procedure EventLoop()                                                           
  ;-----------------------------------------------------------
  ; event loop
  ;-----------------------------------------------------------
  Repeat                                                                        ;; run the loop until QUIT = 1
    ;Debug (eWaitWindow.i)                                                       ;;
    ;Debug (eType.i)                                                             ;;
    ;Debug (gActiveGadget.i)                                                     ;;
    
    gWin_kb_MouseButtonLeft_LastState = gWin_kb_MouseButtonLeft                 ;; grab last state of left mouse key
    gWin_kb_MouseButtonRight_LastState = gWin_kb_MouseButtonRight               ;; grab last state of right mouse button
    gActiveGadgetLast = gActiveGadget                                           ;; grab (last) gadget that has focus
    
    ;; ---------------------------------------------------------
    ;;  grab new needed key states
    ;; ---------------------------------------------------------
    gWin_kb_MouseButtonLeft = GetAsyncKeyState_(#VK_LBUTTON)                    ;; left mouse button
    gWin_kb_MouseButtonRight = GetAsyncKeyState_(#VK_RBUTTON)                   ;; right mouse button
    
    ;;---------------------------------------------------------
    ;; grab new current events
    ;;---------------------------------------------------------
    eWaitWindow = WaitWindowEvent()                                             ;; get event ID (used for resizing)
    eType = EventType()                                                         ;; looking for mouse clicks i.e. left click
    gActiveGadget = GetActiveGadget()                                           ;; the gadget that has the current focus
    
    
    ;;-----------------------------------------------------------
    ;; Check mouse
    ;;-----------------------------------------------------------
    MouseNavigationLeft()                                                       ;; check mouse
    
    ;;-----------------------------------------------------------
    ;; Window Events
    ;;-----------------------------------------------------------
    Select eWaitWindow                                                          ;; (used for resizing, quitting, return key)
      
    Case #PB_Event_SizeWindow                                                   ;; we were resized
      
    Case #PB_Event_CloseWindow                                                  ;; If the user has pressed on the close button
      Quit = 1                                                                  ;; get ready to quit the app
      
    EndSelect                                                                   ;; end of select myEvent
    
  Until Quit = 1                                                                ;; quit is one so we can close all windows
  ;;----------------------------------------------------------
  ;; end event loop
  ;;----------------------------------------------------------
  
EndProcedure

;;------------------------------------------------------------
;; main Program
;;------------------------------------------------------------

EventLoop()                                                                     ;; done - event driven
End                                                                             ;; done - End Program (close any still open windows)
Derek
Addict
Addict
Posts: 2354
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Re: Progress Bar Threaded

Post by Derek »

Can you explain more what it is you're trying to achieve. If you are updating a progressbar in relation to some variable then I can't see why you would want to put it in a thread, you could just call a procedure from your mainloop or even include the update code in your mainloop.

The only reason I can see to put it in a thread is if you want it updating while you are waiting for an input of some kind but in that case what is the progressbar actually indicating.
benco5000
User
User
Posts: 13
Joined: Mon Mar 01, 2010 8:56 pm

Re: Progress Bar Threaded

Post by benco5000 »

Sure.

While processing several files in loop. I'm trying to update an indicator for the end user:

progressBar = Round(currentFile / numberOfFilesToProcess * 100,1)
i.e. here is the actual line of code in my source program (not shown in the example its rather large)

gProgressBarLevel = Round(c / ListSize(fileList()) * 100, 1) ;; calculate the progress bar position

I can do it directly in the main loop, but if the window is clicked or looses focus,
the mainWindow freezes. It never updates again even though it gets the focus
back. I've even tried just updating a text field with the pathName but the response is the same.

I really just need some type of indicator that progress is being made so the end user can check
back periodically to see if its done yet and how much longer it might take.

So I'm trying to put together a test program so I can understand what I need to do to make that happen.
Derek
Addict
Addict
Posts: 2354
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Re: Progress Bar Threaded

Post by Derek »

Code: Select all

Global eWaitWindow.i
Global eType.i
Global gActiveGadget.i

Global progressBarWindow.i = 0
Global gProgressBarGadget.i = 0
Global gProgressBarGadgetLevel.i = 50

Global gDoneYet.i = 0


Global gWinMain = OpenWindow( #PB_Any, 0, 0, 480, 320, "",$ca0001)
Global gbtnprev = ButtonGadget(#PB_Any, 305, 10, 80, 24, "DEC")
Global gBtnNext = ButtonGadget(#PB_Any, 390, 10, 80, 24, "INC")
Global gFieldValue = StringGadget(#PB_Any, 40, 40, 320, 24,"")

If OpenWindow(0, 0, 0, 320, 20, "Progress ...",  $ca0001)
  StickyWindow(0,1)
  gProgressBarGadget = ProgressBarGadget(#PB_Any,0,0,320,20,0,100,#PB_Window_WindowCentered)
EndIf


Procedure progressBar(gdone)
  Repeat
    SetGadgetState(gProgressBarGadget, gProgressBarGadgetLevel)
    Delay(10)
  ForEver
EndProcedure

Thread = CreateThread(@progressBar(), 0)

Repeat
  e=WaitWindowEvent()
  If e=#PB_Event_Gadget
    gad=EventGadget()

    If gad=gbtnprev
      If gProgressBarGadgetLevel > 1
        gProgressBarGadgetLevel = gProgressBarGadgetLevel - 10
        SetGadgetText(gFieldValue, Str(gProgressBarGadgetLevel))
      EndIf
    EndIf

    If gad=gBtnNext
      If gProgressBarGadgetLevel < 100
        gProgressBarGadgetLevel = gProgressBarGadgetLevel + 10
        SetGadgetText(gFieldValue, Str(gProgressBarGadgetLevel))
      EndIf
    EndIf
  EndIf
Until e=#PB_Event_CloseWindow
Here's an example, mostly your code but hacked about.

Incidently, in your original code the textgadget was never being updated and after looking closer it appears the inc and dec bits were never being used.
benco5000
User
User
Posts: 13
Joined: Mon Mar 01, 2010 8:56 pm

Re: Progress Bar Threaded

Post by benco5000 »

Thank you, that should help me.

While we are at it, can you tell me how to make the progress bar window stay inside of gWinMain?
I tried changing the code from:

If OpenWindow(0, 0, 0, 320, 20, "Progress ...", $ca0001)
to
If OpenWindow(0, 0, 0, 320, 20, "Progress ...", $ca0001, gWinMain)

but gives an error message saying:
ParentID is not a a valid WindowID().
Derek
Addict
Addict
Posts: 2354
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Re: Progress Bar Threaded

Post by Derek »

Have a look at the MDIgadget, maybe that could work for you. Other than that it gets complicated.
benco5000
User
User
Posts: 13
Joined: Mon Mar 01, 2010 8:56 pm

Re: Progress Bar Threaded

Post by benco5000 »

Will do. Thanks.
Derek
Addict
Addict
Posts: 2354
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Re: Progress Bar Threaded

Post by Derek »

Using code from Srod, in this thread

http://www.purebasic.fr/english/viewtop ... 74&start=4

Code: Select all

Global eWaitWindow.i
Global eType.i
Global gActiveGadget.i

Global progressBarWindow.i = 0
Global gProgressBarGadget.i = 0
Global gProgressBarGadgetLevel.i = 50

Global gDoneYet.i = 0


Global gWinMain = OpenWindow( #PB_Any, 0, 0, 480, 320, "",$ca0001)
Global gbtnprev = ButtonGadget(#PB_Any, 305, 10, 80, 24, "DEC")
Global gBtnNext = ButtonGadget(#PB_Any, 390, 10, 80, 24, "INC")
Global gFieldValue = StringGadget(#PB_Any, 40, 40, 320, 24,"")

If OpenWindow(0, 0, 0, 320, 20, "Progress ...",  $ca0001)
  StickyWindow(0,1)
  gProgressBarGadget = ProgressBarGadget(#PB_Any,0,0,320,20,0,100,#PB_Window_WindowCentered)
EndIf

;-----------
#APPNAME1 = "Progress ..." 

;Define *Parent 
;Global *Child 


;Procedure MyWindowCallback(hWnd, uMsg, wParam, lParam)
;  result = #PB_ProcessPureBasicEvents
;  Select uMsg
;    Case #WM_PAINT
;        RedrawWindow_(*Child, 0, 0, #RDW_INVALIDATE|#RDW_ERASE|#RDW_FRAME) 
;  EndSelect
;  ProcedureReturn Result
;EndProcedure


*Child = FindWindow_(0, #APPNAME1) 

SetParent_(*Child, WindowID(gwinmain)) 
SetWindowPos_(*Child, 0, 100,100, 0, 0, #SWP_NOSIZE | #SWP_SHOWWINDOW) 
;SetWindowCallback(@MyWindowCallback())


;-----------

Procedure progressBar(gdone)
  Repeat
    SetGadgetState(gProgressBarGadget, gProgressBarGadgetLevel)
    Delay(10)
  ForEver
EndProcedure

Thread = CreateThread(@progressBar(), 0)

Repeat
  e=WaitWindowEvent()
  If e=#PB_Event_Gadget
    gad=EventGadget()

    If gad=gbtnprev
      If gProgressBarGadgetLevel > 1
        gProgressBarGadgetLevel = gProgressBarGadgetLevel - 10
        SetGadgetText(gFieldValue, Str(gProgressBarGadgetLevel))
      EndIf
    EndIf

    If gad=gBtnNext
      If gProgressBarGadgetLevel < 100
        gProgressBarGadgetLevel = gProgressBarGadgetLevel + 10
        SetGadgetText(gFieldValue, Str(gProgressBarGadgetLevel))
      EndIf
    EndIf
  EndIf
Until e=#PB_Event_CloseWindow
You'll need to tidy up the placement of the gadgets etc but its a start for you.

EDIT: Seems there's no need for the callback etc, unless I've overlooked something. :?
Post Reply