Make progress bar disappear before displaying a dialog?

Has anyone solved this problem? If you run this script as an application the progress bar does not disappear before the two dialogs are displayed at the end. The solutions I’ve seen online don’t seem to help:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

on run
	set progress description to "A simple progress indicator"
	set progress additional description to "Preparing…"
	set progress total steps to -1
	delay 0.1
	set progress total steps to 10
	repeat with i from 1 to 10
		try
			set progress additional description to "I am on step " & i
			set progress completed steps to i
			delay 0.1
		on error thisErr
			display alert thisErr
			exit repeat
		end try
	end repeat
	display dialog "The progress bar is stil showing"
	display dialog "And it's still there"
end run

Infigured this out years ago.
I just set progress total steps to 0 and the other progress variables to “”
Then do a delay. If the delay doesn’t work, put it in a repeat loop
Then do the dialogs

@robertfern - Thank you for that. Your method certainly works in the editor, but I can’t make it work in a compiled applet.

Here’s an example with some long delays. Am I doing something wrong?? (I tried setting completed steps to 1 and also tried leaving out that line altogether, but nothing changed.) Thank you again.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

on run
	set progress description to "A simple progress indicator"
	set progress additional description to "Preparing…"
	set progress total steps to -1
	delay 0.1
	set progress total steps to 5
	repeat with i from 1 to 5
		try
			set progress additional description to "I am on step " & i
			set progress completed steps to i
			delay 1
		on error thisErr
			display alert thisErr
			exit repeat
		end try
	end repeat
	delay 5
	set progress total steps to 0
	set progress description to ""
	set progress additional description to ""
	set progress completed steps to 0
	delay 5
	
	activate
	display dialog "The progress bar is stil showing"
end run

Try a repeat loop around the delay

The reason you can’t close the progress bar is because you don’t have access to close its window, and the AppleScript developers didn’t take care of the window closing itself.

To solve your problem, you should use the NSProgressIndicator class + AsObjC code. You create the indicator window yourself, fully controlling its behavior, including closing it when necessary.

Here is a script that I adapted a little for you, but the authors are more advanced programmers. Use it as application:
 

-- Created 2013-10-14 by Shane Stanley
-- © 2013
-- adaption of one of Sal Soghoian's Cocoa-AppleScript applet samples

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
property thisProgressWindow : missing value
property thisProgressIndicator : missing value
property primaryTextField : missing value
property secondaryTextField : missing value
property hitStop : false

on run
	my createProgressWindowWithTitle:"A simple progress indicator" intialMessage:"Preparing…"
	my readyProgressWindowWithMinimum:1 withMaximum:10
	repeat with i from 1 to 10
		(my incrementProgressWindowWithCounter:i itemName:"Processing..." itemCount:10)
		delay 0.2
	end repeat
	my closeProgressWindow()
	display dialog "Progress bar dismissed"
end run

---------------------------------------- OTHER HANDLERS ------------------------------------------

on createProgressWindowWithTitle:initialWindowTitle intialMessage:initialDescriptionString
	try
		set my hitStop to false
		-- create a window
		set thisProgressWindow to current application's NSWindow's alloc()'s initWithContentRect:{{100, 100}, {360, 84}} ¬
			styleMask:(current application's NSTitledWindowMask) ¬
			backing:(current application's NSBackingStoreBuffered) ¬
			defer:true
		-- set the properties of the new window
		thisProgressWindow's setTitle:initialWindowTitle
		thisProgressWindow's setLevel:(current application's NSFloatingWindowLevel)
		thisProgressWindow's |center|()
		-- create a progress indicator
		set thisProgressIndicator to current application's NSProgressIndicator's alloc()'s initWithFrame:{{10, 12}, {280, 20}}
		-- set the properties of the progress indicator
		thisProgressIndicator's setUsesThreadedAnimation:true
		thisProgressIndicator's setStyle:(current application's NSProgressIndicatorBarStyle)
		thisProgressIndicator's setDisplayedWhenStopped:true -- THIS
		thisProgressIndicator's setControlSize:(current application's NSRegularControlSize)
		thisProgressIndicator's setIndeterminate:true
		thisProgressIndicator's startAnimation:thisProgressIndicator
		-- add the progress indicator to the content view of the window
		set thisContentView to thisProgressWindow's contentView()
		tell thisContentView to addSubview:thisProgressIndicator
		-- create a text field
		set primaryTextField to current application's NSTextField's alloc()'s initWithFrame:{{10, 60}, {340, 18}}
		set thisSystemFont to current application's NSFont's systemFontOfSize:13
		primaryTextField's setFont:thisSystemFont
		primaryTextField's setBordered:false
		primaryTextField's setDrawsBackground:false
		primaryTextField's setSelectable:false
		primaryTextField's setEditable:false
		primaryTextField's setStringValue:(initialDescriptionString)
		-- create a second text field
		set secondaryTextField to current application's NSTextField's alloc()'s initWithFrame:{{10, 38}, {340, 18}}
		secondaryTextField's setStringValue:" "
		secondaryTextField's setBordered:false
		secondaryTextField's setSelectable:false
		secondaryTextField's setEditable:false
		secondaryTextField's setDrawsBackground:false
		-- add the text fields to the content view of the window
		tell thisContentView to addSubview:primaryTextField
		tell thisContentView to addSubview:secondaryTextField
		-- create a button
		set thisStopButton to current application's NSButton's alloc()'s initWithFrame:{{296, 10}, {60, 24}}
		thisStopButton's setButtonType:(current application's NSMomentaryPushInButton)
		thisStopButton's setBezelStyle:(current application's NSRoundedBezelStyle)
		thisStopButton's setImagePosition:(current application's NSNoImage)
		thisStopButton's setTitle:"Stop"
		thisStopButton's setTarget:me
		thisStopButton's setAction:"cancelPressed:"
		-- add created button to the content view
		tell thisContentView to addSubview:thisStopButton
		-- display the window
		thisProgressWindow's makeKeyAndOrderFront:thisProgressWindow
		tell current application's NSThread to sleepForTimeInterval:1.0 -- allows screen update
		return true
	end try
	return false
end createProgressWindowWithTitle:intialMessage:

on readyProgressWindowWithMinimum:minimumValue withMaximum:maximumValue
	try
		thisProgressIndicator's setIndeterminate:false
		thisProgressIndicator's setUsesThreadedAnimation:true
		thisProgressIndicator's setMinValue:minimumValue
		thisProgressIndicator's setMaxValue:maximumValue
		thisProgressIndicator's setDoubleValue:minimumValue
		primaryTextField's setStringValue:""
		secondaryTextField's setStringValue:""
		return true
	end try
	return false
end readyProgressWindowWithMinimum:withMaximum:

on incrementProgressWindowWithCounter:thisLoopNumber itemName:thisItemName itemCount:thisItemCount
	if hitStop then
		closeProgressWindow()
		return false
	end if
	try
		primaryTextField's setStringValue:thisItemName
		secondaryTextField's setStringValue:((thisLoopNumber as string) & "/" & (thisItemCount as string))
		primaryTextField's display()
		secondaryTextField's display()
		thisProgressIndicator's incrementBy:1
		thisProgressWindow's makeKeyAndOrderFront:me
		return true
	end try
	return false
end incrementProgressWindowWithCounter:itemName:itemCount:

on cancelPressed:sender
	set my hitStop to true
end cancelPressed:

on closeProgressWindow()
	tell thisProgressWindow to orderOut:thisProgressWindow
end closeProgressWindow

 

1 Like

here is a stay-open app script

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
property doContinue : false

on run
	set progress description to "A simple progress indicator"
	set progress additional description to "Preparing…"
	set progress total steps to -1
	delay 0.1
	set progress total steps to 5
	repeat with i from 1 to 5
		try
			set progress additional description to "I am on step " & i
			set progress completed steps to i
			delay 1
		on error thisErr
			display alert thisErr
			exit repeat
		end try
	end repeat
	set progress total steps to 0
	set progress description to ""
	set progress additional description to ""
	set progress completed steps to 0
	delay 1
	set doContinue to true
end run

on finishRun()
	set doContinue to false
	activate
	display dialog "The progress bar should not be showing" giving up after 10
	quit
end finishRun

on idle
	if doContinue then finishRun()
end idle
2 Likes

I liked your plain AppleScript solution. As I checked, it works. Your script can be simplified. For myself, I saved it in the following form:
 

property doContinue : false

on run
	initializeProgressBar()
	repeat with i from 1 to 5
		set progress additional description to "I am on step " & i
		set progress completed steps to i
		delay 0.5
	end repeat
	set doContinue to true
end run

on initializeProgressBar()
	set progress description to "A simple progress indicator"
	set progress additional description to "Processing…"
	set progress total steps to 5
end initializeProgressBar

on idle
	if doContinue then
		display dialog "Progress bar dismissed"
		quit
	end if
end idle

 

1 Like

@robertfern and @KniazidisR - These solutions are brilliant and effective. A thousand thanks!

@robertfern - Your version of the Shane/Sal script works beautifully, and is exactly what I needed for the script I’ve created, where the progress bar runs between a lot of other prompts and choices.

This is really marvelous work. A thousand thanks again.

1 Like

Does this mean that it is not possible to move the progress bar around the screen?

It would be useful if it could be pushed off to the side so it could still be visible while working in some application window.

And I second @emendelson… these are some nice solutions to the issue.

You can’t change the behaviour of AppleScript progress bar. So, you can’t move it as well.

As I sad, to fully control progress bar behaviour (to be able move it as well) - create your own progress bar using NSProgressIndicator with ASObjC.

Okay, that makes sense. Thanks for clarifying. Maybe I’ll have to dip my toe in the ASObjC water.