cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
Craige_Hales
Super User
Progress Bar with Cancel Button

Progress Bar  showed how to make a progress bar. @abmayfield  question in "not responding" vs. "still thinking"  prompted me to revisit this. Here's another take, including a cancel button.

not cancelednot canceled

Cancel button pressed.Cancel button pressed.

progressBarWidth = 500;
progressUpdatesSeconds = 1 / 4; // 1/2 sec updates -> 1300ips,  1/30 -> 1000ips (1/4 compromise speed vs appearance)
cancel = 0; // clear the cancel flag
New Window( "Progressbar demo", //
	V List Box( //
		cats = Text Box( "" ), // output from the work function
		t = Text Box( "", <<setwrap( 500 ) ), // status of the progressbar
		H List Box( // Duct tape has a light side and a dark side. So does the progressbar.
			left = Spacer Box( size( 0, 10 ), color( "light green" ) ), //
			right = Spacer Box( size( progressBarWidth, 10 ), color( "dark green" ) ), //
			<<padding( 5, 5, 5, 5 ), // gray wrapper
			<<backgroundcolor( "dark gray" ) //
		), //
		cancelButton = Button Box( "Cancel", cancel = 1 ) // sets the cancel flag
	)
);
Wait( 0 ); // allow the window to open, otherwise the updates are not visible

// progressbar variables
startMicroSeconds = HP Time();
workCalls = 0;
recentUpdateMicroSeconds = HP Time();
runSeconds = (recentUpdateMicroSeconds - startMicroSeconds) / 1e6; // so the loop can start
limitSeconds = 10; // time to run the demo

updateProgress = Function( {fractionComplete},
	leftsize = Round( progressBarWidth * fractionComplete );
	rightsize = progressBarWidth - leftsize;
	left << width( leftsize );
	right << width( rightsize );
	t << settext( Eval Insert( "^workCalls^ iterations in ^char(runSeconds,6,3)^ seconds -> ^workCalls/runSeconds^ ips" ) );
	t << updatewindow; // this works without the wait	
);

totalCats = 0;
dowork = Function( {},
	x = "";
	For( i = 1, i <= 1000, i += 1, x = x || "." );
	totalCats += 1000;
	cats << settext( Eval Insert( "total concatenations=^totalCats^" ) );
);

While( runSeconds < limitSeconds & !cancel, // change this to represent the work you are doing
	
	// do some work, simulated by concatenating strings...
	dowork();
	
	// update the progressbar
	workCalls += 1;
	nowMicroSeconds = HP Time();
	// how often does it need to update on the screen?
	If( (nowMicroSeconds - recentUpdateMicroSeconds) / 1e6 > progressUpdatesSeconds, 
		// in this example I'm using a fixed time duration of "limitSeconds" to represent the
		// amount of work to be done. And "runSeconds" to represent the amount of work done so far.
		// Usually you'll have something other than time: number of rows in a table perhaps, or
		// number of categories to make reports for. As long as you know how many total and how
		// many completed, you can compute this fraction...
		updateProgress( runSeconds / limitSeconds );  // change this to represent the fraction of work finished
		recentUpdateMicroSeconds = nowMicroSeconds;
		Wait( 0 ); // this wait is needed to let the cancel button work
	);
	runSeconds = (nowMicroSeconds - startMicroSeconds) / 1e6;
);

If( cancel, // test the cancel flag
	Beep(); // audio flag
	left << color( "dark red" ); // visual flag something is awry
	right << color( "red" );
, //
	updateProgress( 1.0 ); // people like to see the bar go to 100%
);
cancelButton << setbuttonname( "Close" ); // visual flag the button function is changed
cancelButton << setscript( (cancelButton << closewindow) ); // and what to do if the button is pressed

 

Testing between JMP 15 and 16, I noticed 16 is a lot faster on this string concatenation work load! Nice work!

 

Edit: if JMP is running a platform that does not have its own cancelable progress bar, and it runs for a long time, this is not going to help. Tech Support would be a good place to request the platform support for a progress bar. Without it, there is no way (short of forcibly closing JMP) to stop it until it is done.

Last Modified: Nov 5, 2021 11:04 AM
Comments