How to display progress of a for-next loop

Discuss any general programming issues here
Post Reply
amyren
Posts: 352
Joined: Thu May 02, 2019 11:53 am

How to display progress of a for-next loop

Post by amyren »

I have this part of my program that downloads some files and I would like to have a way to display that something is going on so the user doesnt think the app is frozen. The program is RapaGUI based. I did take a look at the progress bar in the Dialogs example, but I am not sure how to implement it in this case.
Alternatively I could also settle just with a small window displaying "Downloading, this might take a a few minutes", that automaticly closes when download finishes.

This For-Next loop processes each year and fetches the corresponding files.

Code: Select all

For i = 1979 To GetDateNum(#DATEYEAR)
  (code to download the files and save them)
Next
Flinx
Posts: 188
Joined: Sun Feb 14, 2021 9:54 am
Location: Germany

Re: How to display progress of a for-next loop

Post by Flinx »

I don't have experience with RapaGUI, but if a small window is possible, then the code from my experiments that I copied here into your example might help. Or you can use the arithmetic of the calculation of progress for RapaGUI.

Code: Select all

EnableLayers()
TextOut(50, 80, "", {Name="Info", Color=#WHITE})

SetFillStyle(#FILLNONE)
layername$="box"
boxX=50
boxY=50
boxW=300
boxH=20
Box(50,50,boxW,20,#GRAY)
SetFillStyle(#FILLCOLOR)

For i = 1979 To GetDateNum(#DATEYEAR)
	Local progress=(i-1979)/(GetDateNum(#DATEYEAR)-1979)
	BeginRefresh()
	SetLayerStyle("Info", {Text="Progress "..ToString(Int(100*progress)).."%"})
	If LayerExists(layername$) Then RemoveLayer(layername$)
	Local width=(boxW-2)*progress
	If width>=1 Then Box(boxX+1,boxY+1,width,boxH-2,#WHITE,{Name=layername$})
	EndRefresh()

	;  (code To download the files And save them)
	Wait(20)
Next
If LayerExists("Info") Then RemoveLayer("Info")
amyren
Posts: 352
Joined: Thu May 02, 2019 11:53 am

Re: How to display progress of a for-next loop

Post by amyren »

Thanks for the suggestion, unfortunately nothing is displayed when I run it, probably because of the way Rapagui works.
User avatar
Redlion
Posts: 94
Joined: Sun Jul 10, 2011 5:05 am
Location: Perth, Western Australia

Re: How to display progress of a for-next loop

Post by Redlion »

@ amyren

I had a few issue getting the progress bar to work in a dialog window, so I just did it at the bottom of the screen.

in your xml code <progressbar id="progress"/>

Code: Select all

moai.Set("progress", "Max", Record -1)
	
	db = sqlite3.open(DB$)
	
	For r = 1 To Record
		db:exec("UPDATE ".. tablename$ .. " SET RecNo = " .. StrStr(r-1) .. " WHERE RowID = " .. StrStr(r) .. "")
		moai.Set("progress", "Level", r)
	Next
	
	db:exec("UPDATE ".. tablename$ .. " SET " .. field[1] .. " = " .. StrStr(Record-1) .. " WHERE RowID = 1")
	db:close()
Substitute the database code for what you need, I Found that you have to set Max to one less than your loop other wise it does not get to the end before its finished.

Cheers
Leo
----------------------------------------------------------------------------------------
Redlion
Sam460 Lite
A4000 A3000 A2000 A1200 A1000 A600 A500 CD32
amyren
Posts: 352
Joined: Thu May 02, 2019 11:53 am

Re: How to display progress of a for-next loop

Post by amyren »

Thanks for the input, I must admit I dont understand half of how RapaGUI works, but it made me have another attempt at this.

Now I do get a working progressbar, but not without issues.
The progressbar dialog only show a blank area where the button is suposed to be.
If I just wait for the download the progressbar will complete, and the dialog will close itself as expected. But if I select either the program main window or activate the progressbar dialog window, the progessbar will stop updating and apearently the whole will get a "not responding" status,
But it does continue the download, but after downloading the button will apear and the progressbar dialog will stay on screen and I am unable to close it. The main program will continue working though.

Here is my progress.xml file

Code: Select all

<?xml version="1.0" encoding="iso-8859-1"?>	
<dialog id="dnlprog" title="Vennligst vent, laster ned data..." width="300" closegadget="false">
	<vgroup>
		<progressbar id="prgbar"/>
		<button id="avbryt" hint="negative">Avbryt!</button>	
	</vgroup>					
</dialog>

In my download function I have added some of the code from the Dialogs example (progress.xml is file 11)

Code: Select all

Function p_download_all()
	If IsOnline()
		abortpressed = False	
		Seek(11, 0)
		moai.CreateDialog(ReadString(11), "win")
		moai.Set("app", "sleep", True)
		moai.Set("dnlprog", "open", True)
		moai.Set("prgbar", "Max", GetDateNum(#DATEYEAR)-1979)
		moai.Set("prgbar", "Level", 1)	
		For i = 1979 To GetDateNum(#DATEYEAR)
			If abortpressed = True ; abort button pressed
				moai.Request("", "Download aborted!", "OK", "error")
				Break
			EndIf

			,,,some download code....
			
			moai.Set("prgbar", "Level", i-1978)
		Next
		
		moai.Set("app", "sleep", False)
		moai.Set("dnlprog", "open", False)

		moai.Request("", "Download finished!", "OK")

	endif
Endfunction
User avatar
airsoftsoftwair
Posts: 5433
Joined: Fri Feb 12, 2010 2:33 pm
Location: Germany
Contact:

Re: How to display progress of a for-next loop

Post by airsoftsoftwair »

If you can't get it working, post an MCVE and I'll take a look.
amyren
Posts: 352
Joined: Thu May 02, 2019 11:53 am

Re: How to display progress of a for-next loop

Post by amyren »

airsoftsoftwair wrote: Sat Mar 25, 2023 9:07 pm If you can't get it working, post an MCVE and I'll take a look.
Here is a small example

Code: Select all

@REQUIRE "RapaGUI"
@FILE 1, "Dialogs.xml"
@FILE 2, "progress.xml"

Function p_Test_progress()
	If IsOnline()
		abortpressed = False	
		Seek(2, 0)
		moai.CreateDialog(ReadString(2), "win")
		moai.Set("app", "sleep", True)
		moai.Set("dnlprog", "open", True)
		moai.Set("prgbar", "Max", GetDateNum(#DATEYEAR)-1979)
		moai.Set("prgbar", "Level", 1)	
		For i = 1979 To GetDateNum(#DATEYEAR)
			If abortpressed = True ; abort button pressed
				moai.Request("", "Progressbar aborted!", "OK", "error")
				Break
			EndIf
			DebugPrint(i)
			Wait(10)			
			moai.Set("prgbar", "Level", i-1978)
		Next
		
		moai.Set("app", "sleep", False)
		moai.Set("dnlprog", "open", False)

		moai.Request("", "Progressbar finished!", "OK")
	EndIf
EndFunction

Function p_EventFunc(msg)
	Switch msg.action
	Case "RapaGUI":
		Switch msg.attribute
		Case "Active":
			p_RefreshButtons(msg.triggervalue)
		Case "Pressed":
			Switch msg.id
			Case "exit"
				End				
			Case "Start"
				p_Test_progress
			Case "abort"
				abortpressed = True																									
			EndSwitch	
		EndSwitch
	EndSwitch
EndFunction

moai.CreateApp(ReadString(1))

InstallEventHandler({RapaGUI = p_EventFunc})

; main loop!
Repeat
	WaitEvent
Forever
Dialogs.xml

Code: Select all

<?xml version="1.0" encoding="iso-8859-1"?>
<application id="app">
	<window id="win" title="Dialogs" width="400" height="300" >
		<vgroup>
			<hgroup>
				<button id="Start">Start</button>
				<button id="exit">Quit</button>
			</hgroup>			
		</vgroup>
	</window>		
</application>
progress.xml

Code: Select all

<?xml version="1.0" encoding="iso-8859-1"?>	
<dialog id="dnlprog" title="Vennligst vent, laster ned data..." width="300" closegadget="false">
	<vgroup>
		<progressbar id="prgbar"/>
		<button id="avbryt" hint="negative">Avbryt!</button>	
	</vgroup>					
</dialog>
Flinx
Posts: 188
Joined: Sun Feb 14, 2021 9:54 am
Location: Germany

Re: How to display progress of a for-next loop

Post by Flinx »

Hello Andreas, here you see how the clueless think ...
I had experimented too, and tried to include the loop in p_DialogFunc(), omitting the "recursive" call to the function via RunCallback().
As a result, I expected to get the progressbar dialog, but without a working button because WaitEvent is not reached. Instead, it resulted in exactly the behavior amyren described later (empty area instead of button and dialog box that wouldn't close). That's when I let it go for now and didn't reply here because I didn't understand it.
But since we both seem to have done the same things wrong, I wanted to understand what was happening, so now I've tried some more.

amyren: A For loop is unsuitable here, because RapaGUI reacts to events, and it is therefore necessary that WaitEvent is called regularly. I have therefore replaced the variable i with the argument msg.userdata of the function p_DialogFunc(msg).
Instead of the For loop, this function calls itself via RunCallback until userdata reaches the final value (similar to what it does in the original version). This way every single loop pass is called by an event.

If you replace p_DialogFunc() in the original Dialogs.hws with this version, you will have the desired behavior.
The structure is still a bit strange (the function is first called with argument 0, so I set userdata to 1979 first), but you can make this nicer. For example you could use a global variable instead of the function argument. And the three 1979 should also be replaced by a variable or constant.

Code: Select all

Function p_DialogFunc(msg)

	If Not msg.userdata>0
		msg.userdata=1979
	EndIf

	; update progress bar
	Local progress=(msg.userdata-1979)/(GetDateNum(#DATEYEAR)-1979)*100
	moai.Set("prgbar", "level", progress)

	If msg.userdata>GetDateNum(#DATEYEAR)
		; "loop" finished
		p_ShowHideDialog("dlg2", False)
	ElseIf abortpressed
		p_ShowHideDialog("dlg2", False)
	Else
		;DebugPrint(msg.userdata)
		; (code To download ONE file and save it)
		RunCallback(p_DialogFunc, msg.userdata + 1)	
	EndIf

	Wait(20, #MILLISECONDS)			
EndFunction
Edit: In the meantime you have also replied. Maybe my example will help anyway.
amyren
Posts: 352
Joined: Thu May 02, 2019 11:53 am

Re: How to display progress of a for-next loop

Post by amyren »

Thanks, I think I got something cooking now.
I got my example to work now, just need to find how to apply the same into my main program.

modyfied example

Code: Select all

@REQUIRE "RapaGUI"
@FILE 1, "Dialogs.xml"
@FILE 2, "progress.xml"

Function p_Test_progress()
	If IsOnline()
		Seek(2, 0)
		moai.CreateDialog(ReadString(2), "win")
		moai.Set("app", "sleep", True)
		moai.Set("dnlprog", "open", True)
		moai.Set("prgbar", "Max", GetDateNum(#DATEYEAR)-1979)
		p_DialogFunc({userdata = 0})
		;p_DialogFunc({1979})
	EndIf
EndFunction

Function p_DialogFunc(msg)

	If Not msg.userdata>0
		msg.userdata=1979
	EndIf

	; update progress bar
	Local progress=(msg.userdata-1979)/(GetDateNum(#DATEYEAR)-1979)*100
	moai.Set("prgbar", "level", progress)

	If msg.userdata>GetDateNum(#DATEYEAR)
		; "loop" finished
		p_ShowHideDialog("dnlprog", False)
	ElseIf abortpressed
		p_ShowHideDialog("dnlprog", False)
	Else
		;DebugPrint(msg.userdata)
		; (code To download ONE file and save it)
		;p_loadone
		yearcount = msg.userdata
		p_loadone
		RunCallback(p_DialogFunc, msg.userdata + 1)	
	EndIf

	Wait(200, #MILLISECONDS)			
EndFunction

Function p_ShowHideDialog(dlg$, flag)
	
	If flag
		moai.Set("app", "sleep", True)
		moai.Set("dnlprog", "open", True)
	Else
		moai.Set("dnlprog", "open", False)
		moai.FreeDialog("dnlprog")	
		moai.Set("app", "sleep", False)	
	EndIf
					
EndFunction


Function p_EventFunc(msg)
	Switch msg.action
	Case "RapaGUI":
		Switch msg.attribute
		Case "Pressed":
			Switch msg.id
			Case "exit"
				End				
			Case "Start"
				p_Test_progress
			Case "avbryt"
				abortpressed = True																									
			EndSwitch	
		EndSwitch
	EndSwitch
EndFunction

Function p_loadone()
	DebugPrint(yearcount)
EndFunction

moai.CreateApp(ReadString(1))

InstallEventHandler({RapaGUI = p_EventFunc})

; main loop!
Repeat
	WaitEvent
Forever

Post Reply