Refresh Progressbar gadget

Just starting out? Need help? Post your questions and find answers here.
PMV
Enthusiast
Enthusiast
Posts: 727
Joined: Sat Feb 24, 2007 3:15 pm
Location: Germany

Re: Refresh Progressbar gadget

Post by PMV »

Just have in mind, that a progress bar is just for a user to show
a progress of something. A user don't cares about a progress bar,
that doesn't get filled up completely but vanishes when a task is
finished.

Additional, on Vista/ 7 the progress bar is just 1 or 2 seconds
behind the real value, so if you doesn't close the progress bar,
it will be filled up that seconds later. No need to worry about
that. :wink:

There are just 2 things you could do to have a better experience
with this animated progress bar:
1. If you have just a small progress max. value, multiply that
with 10, otherwise the progress bar jumps between the steps.
2. Set the progress bar state to the state where you are on, and
not to that step that is finished. So if you have 10 steps, set
the progress to step 1 at the beginning and for example to step
10 if you are computing step 10. The progress bar will be filled up
while the program is computing that step and when it is finished,
the bar is already filled.

Just my two cent. :)

A, forgotten: May be this works ... ifyou really need to have the
progress bar filled immediately set the max value to 1 and the
progress state to 1 two, as because for 1 step there is no
space for animation, maybe it is filled immediatly

MFG PMV
Barbarossa
User
User
Posts: 47
Joined: Fri Oct 12, 2012 8:50 am

Re: Refresh Progressbar gadget

Post by Barbarossa »

@Danilo

Works like a charm now!

I also put the refreshprocedure at the beginning of the loop instead of at the end of the loop. That also gives better results.

John
Barbarossa
User
User
Posts: 47
Joined: Fri Oct 12, 2012 8:50 am

Re: Refresh Progressbar gadget

Post by Barbarossa »

PMV wrote:Just have in mind, that a progress bar is just for a user to show
a progress of something. A user don't cares about a progress bar,
that doesn't get filled up completely but vanishes when a task is
finished.
Very true. That is also the reason that I settled for almost perfect and decided to move on. The reason for trying is that I am a perfectionist in nature and it bothers me. :)
PMV wrote: Additional, on Vista/ 7 the progress bar is just 1 or 2 seconds
behind the real value, so if you doesn't close the progress bar,
it will be filled up that seconds later. No need to worry about
that. :wink:
That is the core of the problem. I did tinker with the idea to not close the bar and close it afterwards from my mainloop. I did not do that for 2 reasons:
1. I will need a timer in the mainloop to create a delay before I can close the bar.
2. The output is already presented to the user and the bar is still running!
PMV wrote: There are just 2 things you could do to have a better experience
with this animated progress bar:
1. If you have just a small progress max. value, multiply that
with 10, otherwise the progress bar jumps between the steps.
2. Set the progress bar state to the state where you are on, and
not to that step that is finished. So if you have 10 steps, set
the progress to step 1 at the beginning and for example to step
10 if you are computing step 10. The progress bar will be filled up
while the program is computing that step and when it is finished,
the bar is already filled.
I already figured out tip 2 (didn't read your post before I posted mine). It works better but since my last 10 iterations take up very little time this also doesn't fill up the bar completely.


Thank you for your input.
rootboy
New User
New User
Posts: 3
Joined: Tue Apr 09, 2013 7:45 pm

Re: Refresh Progressbar gadget

Post by rootboy »

Danilo wrote:To make it work for the maximum value, you could change the range maximum temporarily (add 1), set maximum value, set maximum-1 value, change range maximum back to old maximum (sub 1).
Works great, thanks!
nalor
Enthusiast
Enthusiast
Posts: 121
Joined: Thu Apr 02, 2009 9:48 pm

Re: Refresh Progressbar gadget

Post by nalor »

Hi!

Here comes a small example from my side - it is based on danilo's 'non-blocking' example but shows it in a more final version, I've a main window with 2 buttons to start 2 different actions where each displays a progress bar.
ProgressBar refreshing is done in the main event loop, so it's constantly updated an even updates automatically until the end - no need to play with setting 'value+1' and next 'value'.

At least on my win7x64 everything is working fine :)

Code: Select all

EnableExplicit

Enumeration #PB_Compiler_EnumerationValue
	#MainWin
	#ProgressWin
EndEnumeration

Enumeration #PB_Compiler_EnumerationValue
	#HeavyWorkButton
	#LightWorkButton
	
	#Progress_Text
	#Progress_Bar
	#Progress_Cancel
EndEnumeration

Define StopTheWork.b
Define StopTheWorkMutex=CreateMutex()

;- Thread Variables
Define TH_Work.i ; ThreadId Work

;- Declarations
Declare StartHeavyWork()
Declare StartLightWork()

Procedure OpenMainWin()
  OpenWindow(#MainWin, 0, 0, 390, 100, "ProgressBarTest", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(#HeavyWorkButton, 40, 30, 130, 30, "Start HeavyWork")
  ButtonGadget(#LightWorkButton, 220, 30, 130, 30, "Start LightWork")
EndProcedure

Procedure MainWin_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False

    Case #PB_Event_Gadget
    	Select EventGadget()
    		Case #HeavyWorkButton
    			StartHeavyWork()
    			
    		Case #LightWorkButton
    			StartLightWork()
    			
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure

Procedure OpenProgressWin(Title.s, Text.s, MaxVal.i)
  OpenWindow(#ProgressWin, 0, 0, 440, 130, Title, #PB_Window_TitleBar | #PB_Window_WindowCentered, WindowID(#MainWin))
  ButtonGadget(#Progress_Cancel, 150, 90, 140, 30, "Cancel")
  ProgressBarGadget(#Progress_Bar, 10, 50, 420, 30, 0, MaxVal)
  TextGadget(#Progress_Text, 10, 20, 420, 20, Text, #PB_Text_Center)	
EndProcedure

Procedure ProgressWin_Events(event)
	Shared StopTheWork
	Shared StopTheWorkMutex	
	Shared TH_Work
	
	Select event
		Case #PB_Event_Gadget
			Select EventGadget()
			Case #Progress_Cancel
				If IsThread(TH_Work)
					LockMutex(StopTheWorkMutex)
					StopTheWork=#True
					UnlockMutex(StopTheWorkMutex)
				Else
					CloseWindow(#ProgressWin)
					DisableWindow(#MainWin, 0)
				EndIf
			EndSelect
	EndSelect
	ProcedureReturn #True
EndProcedure


Procedure Thread_HeavyWork(Value.i)
	
	Protected i
	Protected StopTheWorkLocal.b=#False
	Shared StopTheWork
	Shared StopTheWorkMutex	
	
	For i = 1 To 10
		
		Delay(1000)  ; >> this simulates the "heavy work" ;)
		
		If IsWindow(#ProgressWin)
			SetGadgetText(#Progress_Text, "HeavyWork Step "+Str(i)+"/10 finished!")
			SetGadgetState(#Progress_Bar, i*10)
		EndIf
		
		LockMutex(StopTheWorkMutex)
		StopTheWorkLocal=StopTheWork
		UnlockMutex(StopTheWorkMutex)     	
		
		If StopTheWorkLocal
			Break
		EndIf
	Next i
	
	If IsWindow(#ProgressWin)
		If StopTheWorkLocal
			SetGadgetText(#Progress_Text, "Heavy Work stopped!")
		Else
			SetGadgetText(#Progress_Text, "Heavy Work finished!")
		EndIf

		SetGadgetText(#Progress_Cancel, "Close")
	EndIf
 	
EndProcedure

Procedure StartHeavyWork()
	
	Shared StopTheWork
	Shared StopTheWorkMutex
	
	Shared TH_Work
	
	LockMutex(StopTheWorkMutex)
	StopTheWork=#False
	UnlockMutex(StopTheWorkMutex)
	
	DisableWindow(#MainWin, 1)
	
	OpenProgressWin("HeavyWork", "Progress of the HeavyWork!", 100)
	
	TH_Work=CreateThread(@Thread_HeavyWork(), 0)
	
EndProcedure

Procedure Thread_LightWork(Value.i)
	
	Protected i
	Protected StopTheWorkLocal.b=#False
	Shared StopTheWork
	Shared StopTheWorkMutex	
	
	For i = 1 To 50
		
		Delay(200) ; >> this simulates the "light work" ;)
		
		If IsWindow(#ProgressWin)
			SetGadgetText(#Progress_Text, "LightWork Step "+Str(i)+"/50 finished!")
			SetGadgetState(#Progress_Bar, i)
		EndIf
		
		LockMutex(StopTheWorkMutex)
		StopTheWorkLocal=StopTheWork
		UnlockMutex(StopTheWorkMutex)     	
		
		If StopTheWorkLocal
			Break
		EndIf
	Next i
	
	If IsWindow(#ProgressWin)
		If StopTheWorkLocal
			SetGadgetText(#Progress_Text, "Light Work stopped!")
		Else
			SetGadgetText(#Progress_Text, "Light Work finished!")
		EndIf

		SetGadgetText(#Progress_Cancel, "Close")
	EndIf
 	
EndProcedure

Procedure StartLightWork()
	
	Shared StopTheWork
	Shared StopTheWorkMutex
	
	Shared TH_Work
	
	LockMutex(StopTheWorkMutex)
	StopTheWork=#False
	UnlockMutex(StopTheWorkMutex)
	
	DisableWindow(#MainWin, 1)
	
	OpenProgressWin("LightWork", "Progress of the LightWork!", 50)
	
	TH_Work=CreateThread(@Thread_LightWork(), 0)
	
EndProcedure

Define iEvent.i
Define iEventWindow.i
Define iCloseAll.i

OpenMainWin()

Repeat

	iEvent = WaitWindowEvent(100)
	
	Select iEvent
		Case 0 ;timeout
				
		Default			
			iEventWindow=EventWindow()
			
			Select iEventWindow
				Case #MainWin
					If Not MainWin_Events(iEvent)
						iCloseAll=#True
					EndIf
					
				Case #ProgressWin
					If Not ProgressWin_Events(iEvent)
						iCloseAll=#True
					EndIf					
					
			EndSelect
	EndSelect

Until iCloseAll=#True
Have fun!
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Refresh Progressbar gadget

Post by electrochrisso »

Good example nalor, thanks for sharing. :)
PureBasic! Purely the best 8)
Post Reply