How do I animate a determinate progress indicator?

G’day

I’ve got a scrolling progress indicator that’s not actually scrolling as it lengthens. The blue diamonds are fixed, and not moving as they should.

Does anyone have any idea how to get it to animate please? The ‘usesThreadedAnimation’ doesn’t work.

Regards

Santa


Progress's usesThreadedAnimation(true)
			Progress's incrementBy_(1)
			Progress's displayIfNeeded()


Get rid of the usesThreadedAnimation (which should be usesThreadedAnimation_ to work), and get rid of displayIfNeeded.

G’day Shane, & thanks

Unfortunately ‘Progress’s incrementBy_(1)’ didn’t work on it’s own; in order to get the indicator to work it needs updating with ‘displayIfNeeded’, and in order to get it to animate it needed the ‘setUsesThreadedAnimation’ line below. Without them there’s only a sudden update when the script finishes.

Regards

Santa



on UpDateProgress(incP)
		repeat incP times
			Progress's setUsesThreadedAnimation_(true)
			Progress's incrementBy_(1)
			Progress's displayIfNeeded()
		end repeat
	end UpDateProgress

That suggests your problem is actually elsewhere.

Let me guess: you have a handler triggered by a button, and the attempt to update is happening in that handler, yes?

I would log the start and end of the handler (or more) to check.

G’day Shane

GREAT guess! (estimation)

I’ve got 6 checkboxes that determine if certain reports on data bases are sent, and the code is called by a button that stays blue until the code is finished.

Regards

Santa

And that’s your real problem. When you push the button, the event is sent to your handler, and the button isn’t released until the handler is finished – meanwhile your dialog is blocked. If you look at the first example here http://www.scriptingmatters.com/ASObjC, you’ll see the same thing, and the solution.

G’day again Shane.

I’ve followed the tutorial, and struck a problem. I can’t for the life of me work out how you bind the ‘isidle’ to the Referencing Bindings.

I don’t even have a group called ‘Referencing Bindings’ to try and work with.

I’ve scoured the net but can’t find a tutorial that explains how to go about creating the bindings.

Can you advise please?

Regards

Santa

It’s OK, I figured it out.

However, I still need to use the following, presumably because I’m triggering the routine from within handler loops.

It gives a nice smooth action, whereas without the line ‘displayIfNeeded’ it is very jerky.

BUT, the button is no longer blue.


on UpDateProgress(incP)
		repeat incP times
			Progress's setUsesThreadedAnimation_(true) 
			Progress's incrementBy_(1)
			Progress's displayIfNeeded()
		end repeat
	end UpDateProgress
	

Oops, I posted too soon. Turns out that the routine only works once, then on subsequent runs refuses to draw as all.

I had the progress indicator set to hide when not drawing, so set it to visible. Now it won’t even draw the first time.

I removed the line ‘Progress’s setUsesThreadedAnimation_(true)’ and it works, but doesn’t animate.

I’ve tried binding the indicator to the Animate setting, bound to a true property, but still no animation.

Anybody got any ideas on what to do please. The scrolling looks pitiful when it’s not animated.

Regards

Santa

You do it in Interface Builder, in the Bindings panel of the Inspector.

But it’s not bindings or lack of it that is your problem; it’s the need to use performSelector_withObject_afterDelay_ so that your handler can return quickly. Doing that will solve the problem that setUsesThreadedAnimation_ and displayIfNeeded cannot.

G’day Shane

I’ve worked out how to bind to ‘isIdle’, and I’ve included the performSelector_withObject_afterDelay_ handler, but I still needed the ‘displayIfNeeded’ to give a smooth animation, otherwise it ‘jerked’ from one position to the next, in large increments.

However it doesn’t animate. I see in the connections inspector a ‘startAnimation’ but can’t figure out how to use it. Is it required?

I’ve bound the ‘Animate’ to a property set to true, but it’s still not animating.

Regards

Santa

That’s the way it works: you tell it to be a number, and a number it is. If you want finer steps, you need to use a bigger range of numbers. The animation stuff you’re playing with is for indeterminate progress bars, not ones where you set the value.

G’day Shane

That’s what I’m doing, but I’m calling the small incrementing routine from within loops, and even though I’m using large numbers, it still jerks from the number at the beginning of the loop, to the number at the end, unless I use the ‘displayIfNeeded’.

I’ll attach a part of my script so you can see one loop that calls it for hundreds of times ( don’t ask why).

Of more importance to me atm is why isn’t it animating?

How on earth do I bind the startAnimation to the progress indicator?

Regards

Santa


on ClientReport()
		set DataClientYear to theYear's titleOfSelectedItem() as integer
		set TallyName2 to (TempTallyName & "Mail Data " & DataClientYear) as text
		set TestClientDate to current date
		set EndClientDate to current date
		set year of TestClientDate to DataClientYear
		set month of TestClientDate to (startingMonth's indexOfSelectedItem()) + 1
		set day of TestClientDate to 1
		set the hours of TestClientDate to 0
		set the minutes of TestClientDate to 0
		set the seconds of TestClientDate to 0
		set year of EndClientDate to DataClientYear
		set month of EndClientDate to (endingMonth's indexOfSelectedItem()) + 1
		set day of EndClientDate to 1
		set the hours of EndClientDate to 0
		set the minutes of EndClientDate to 0
		set the seconds of EndClientDate to 0
		set HourlyString to {}
		set MonthlyString to {} --{"¢¢¢¢¢¢¢¢¢¢¢ Data for clients starting " & TestClientDate & "¢¢¢¢¢¢¢¢¢¢¢" & return & return}
		set tempStartingMonth to month of TestClientDate as integer
		set tempendingmonth to month of EndClientDate as integer
		set theClientList to {}
		set theClientList2 to {}
		tell application "Finder"
			set theFiles to files of folder TallyName2
			set xx to 0
			repeat with individualFile in theFiles
				my UpDateProgress(10) ---<---  increment progress indicator
				set theCreationDate to creation date of individualFile
				set theCMonth to month of theCreationDate as integer
				if theCMonth ≥ tempStartingMonth and theCMonth ≤ tempendingmonth then
					set tempWholeList to my ReadFile2(individualFile as text) as list
					repeat with paragraphCycle in paragraphs of item 1 of tempWholeList -- run through the clients in .dat
						try
							set x to offset of "," in paragraphCycle
							set y to offset of ">" in paragraphCycle
							set tempClientString to characters (x + 1) thru y of paragraphCycle as text
							set exitFlag to false
							set ContentCount to count of items of theClientList
							set theCycleLoop to 100
							if theCycleLoop > ContentCount then set theCycleLoop to ContentCount
							if ContentCount ≠ 0 then
								repeat with x from 1 to ContentCount by theCycleLoop
									set y to x + theCycleLoop
									if y ≥ ContentCount then set y to ContentCount
									set tempstring to items x thru y of theClientList
									repeat with tempCycle from 1 to count of items of tempstring -- now check through existing clients
										if tempClientString = item tempCycle of tempstring as text then
											set item (tempCycle + x - 1) of theClientList2 to (item (tempCycle + x - 1) of theClientList2) + 1
											set exitFlag to true
											exit repeat
										end if
									end repeat
									if exitFlag then exit repeat
								end repeat
							end if
							if not exitFlag then
								if tempClientString ≠ "" then
									set end of theClientList to tempClientString
									set end of theClientList2 to 1
								end if
							end if
						on error errmsg
							--display dialog errmsg
						end try
					end repeat
				end if
			end repeat
		end tell
		set thecount to count of theClientList
		set theincrement to 20 / thecount
		set incCount to 0
		repeat with x from 1 to thecount
			set incCount to incCount + theincrement
			if incCount > 1 then
				my UpDateProgress(4)
				set incCount to 0
			end if
			set t to item x of theClientList
			repeat
				if character 1 of t is in {"\"", " ", "?"} then
					set tt to characters 2 thru (count of t) of t as text
					set item x of theClientList to tt
					set t to tt
				else
					exit repeat
				end if
			end repeat
			if character 1 of t = "<" then
				set t to characters 2 thru -1 of t & "<" as text
				set item x of theClientList to t
			end if
		end repeat
		set {temp4, temp3} to my sort2Lists(theClientList, theClientList2)
		set temp1 to {}
		set temp2 to {}
		set incCount to 0
		repeat with x from (count of temp4) to 1 by -1
			set incCount to incCount + theincrement
			if incCount > 1 then
				my UpDateProgress(4)
				set incCount to 0
			end if
			set end of temp1 to item x of temp3
			set t to item x of temp4
			if character -1 of t = "<" then
				set t to "<" & characters 1 thru -2 of t as text
			end if
			set end of temp2 to t -- ClientList
		end repeat
		set DisplayAlphabetString to {}
		set incCount to 0
		repeat with x from (count of temp1) to 1 by -1
			set incCount to incCount + theincrement
			if incCount > 1 then
				my UpDateProgress(4)
				set incCount to 0
			end if
			set tempfill to ""
			if item x of temp1 as integer < 1000 then set tempfill to (ASCII character of 9)
			set end of DisplayAlphabetString to item x of temp1 & tempfill & (ASCII character of 9) & item x of temp2 & return
		end repeat
		set {temp1, temp2} to my sort2Lists(temp1, temp2)
		set DisplayString to {}
		set incCount to 0
		repeat with x from (count of temp1) to 1 by -1
			set incCount to incCount + theincrement
			if incCount > 1 then
				my UpDateProgress(4)
				set incCount to 0
			end if
			set tempfill to ""
			if item x of temp1 as integer < 1000 then set tempfill to (ASCII character of 9)
			set end of DisplayString to item x of temp1 & tempfill & (ASCII character of 9) & item x of temp2 & return
		end repeat
		my CheckOK()
	end ClientReport
	
	

You’re not listening: you don’t. startAnimation is for indeterminate progress bars.

You seem to be doing a lot of incrementing – what have you set as the bar’s maximum value?

Ummm, haven’t read all this post but last time I checked you DO need startAnimation for INdeterminate progressers.

Right – but this code is not meant for an indeterminate progress bar.

Shane, I am listening, but even though I’ve done everything you suggested, the bar isn’t animating. I’m simply trying to find a reason why is damnwell isn’t.

At least when I was not doing things ‘right’ I had an animating progress indicator. I would like one now as well, or I’ll go back to my old ‘incorrect’ script.

Solve this and I’ll shout you a beer if you’re ever in Bendigo.

The indicator is definitely determinate, it has NOT got a barber pole in interface builder.

As for the lot of incrementing, I’ve got 6 possible handlers that a user can select from, 1 thru all of them. Some execute in a few seconds, one (which I posted) takes several minutes. I’ve ‘weighted’ the long one so the progress bar slides along evenly according to the time each takes, not ‘jerking’ from one to the next. I’m fussy about things like that.

In other words, the four minute one uses about 80% of the bar, which is about 11cm long.

Regards

Santa

I’ll ask again: what have you set as the bar’s maximum value?

?