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 cancelednot cancelednot cancelednot canceled
Cancel button pressed.Cancel button pressed.Cancel button pressed.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> ^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
</SETWRAP>
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.
It does want to be packaged, thanks!
In your example, pb<
You've also pointed out something I missed in How to use Define Class : I thought I needed to lay out the class members explicitly in the define class prototype, but this: can create them too.
Define Class("bubble",
//not needed: m_xpos = .;
_init_ = Method( {x}, <BR />//because using explicit this: ...
this:m_xpos = x;
Thanks @Craige_Hales ! I happened to need progress bar (or something similar) to one of my scripts, so I took this and modified it a bit to fit my needs. I turned it into a class ('m very beginner with JMP's classes and classes in general) for practice and because I felt like it could fit into one. I also added some documentation which can be parsed with Natural Docs.
Code:
View more...Natural docs will look something like this:
