cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
juliagong
Staff (Retired)
How to create a JMP user interface using display boxes in JSL

JMP has a friendly point-and-click interface, and the scripting language in JMP, JSL, can be used to create some of your own. I did a lot of display box manipulation when building my JMP add-in, the JMP to R Custom Add-In Builder. Using display box commands to create a custom user interface (UI) can be challenging for new JMP scripters, so I put together a series of examples that have the main components of a JMP interface you might want to create.

In addition to the case study here, you might find the JMP display box documentation on common display box organization and an advanced example (search “Advanced Example”) with interactive display elements helpful, as well as the resources I detail in another blog post, Display Box Construction 101.

The two main types of organizations for UI display boxes are V List Box() and H List Box(). V List Box will glue components together vertically, while H List Box will glue components together horizontally. You can nest V and H List Boxes to create the exact organization of elements that you need. For example, if you wanted to create this simple window:

 

Example 1: A simple UIExample 1: A simple UI

You will need to use both V and H List Boxes to hold the components you use (Check Box, Panel Box, Radio Box). Use a V List Box, as your components are all ordered vertically, to create the overall display.

Then, within the vertically aligned items, use H List Boxes to hold the items that need to be organized horizontally — for example, the A, B, and C Check Boxes. Repeat this with all of your components, including the Panel Box that holds Radio Boxes within it.

The script for this example is below:

New Window("Letters",
       V List Box(Align(center),
              H List Box(
                     Spacer Box(Size(10, 15)),
                     Text Box("Select all of the letters your heart desires."),
                     Spacer Box(Size(10, 10))
              ),
             
              Spacer Box(Size(20, 10)),
             
              H List Box(
                     Check Box("A"),
                     Check Box("B"),
                     Check Box("C")
              ),
             
              Spacer Box(Size(20, 10)),
             
              Panel Box("Select some more...",
                     Radio Box({"D", "E", "F", "G", "H"})
              ),
             
              Spacer Box(Size(20, 10)),
             
              H List Box(Align(center),
                     Check Box("I"),
                     Check Box("J"),
                     Check Box("K")
              ),
             
              Spacer Box(Size(10, 10))
       );
);

 

But what if you want more? The same goes if you want to create a more intricate combination of nested vertical and horizontal displays, as in this UI:

 

Example 2: Even more nested V and H List BoxesExample 2: Even more nested V and H List Boxes

The corresponding JSL for this UI is:

New Window("Letters 2.0",
       V List Box(Align(center),
              H List Box(
                     Spacer Box(Size(10, 15)),
                     Text Box("Select all of the letters your heart desires."),
                     Spacer Box(Size(10, 10))
              ),
             
              Spacer Box(Size(20, 10)),
             
              H List Box(
                     Check Box("A"),
                     Spacer Box(Size(10, 10)),
                     Check Box("B"),
                     Spacer Box(Size(10, 10)),
                     Check Box("C")
              ),
             
              Spacer Box(Size(20, 10)),
             
              H List Box(
                     Spacer Box(Size(20, 10)),
                    
                     Panel Box("Select some more...",
                           Radio Box({"D", "E", "F", "G", "H"})
                     ),
                    
                     Panel Box("And another...",
                           Radio Box({"I", "J", "K", "L", "M"})
                     ),
                    
                     Spacer Box(Size(10, 10)),
                                        
                     V List Box(
                           Spacer Box(Size(10, 1)),
                           Text Box("What are your favorite letters?"),
                           Spacer Box(Size(10, 10)),
                           Text Edit Box("add your own"),
                           Spacer Box(Size(10, 10)),
                           Text Edit Box("add your own"),
                           Spacer Box(Size(10, 10)),
                           Text Edit Box("add your own"),
                     ),
                    
                     Spacer Box(Size(20, 10)),
              ),
             
              Spacer Box(Size(20, 20)),
             
              H List Box(
                     Spacer Box(Size(10, 15)),
                     Text Box("Which of these SAS Cary buildings is your favorite?"),
                     Spacer Box(Size(10, 10))
              ),
             
              Spacer Box(Size(20, 10)),
             
              H List Box(Align(center),
                     Check Box("S"),
                     Spacer Box(Size(10, 10)),
                     Check Box("T"),
                     Spacer Box(Size(10, 10)),
                     Check Box("U")
              ),
             
              Spacer Box(Size(10, 10))
       );
);

 

Notice how, for visual appeal, I add Spacer Boxes around the edges of display boxes to pad them.

But what about data tables, column selects, and column lists, you ask? You may want to create a useful column selection dialog with some other elements, like Check Boxes, thrown in:

Example 3: Using Col List BoxesExample 3: Using Col List Boxes

The principle behind this display is the same. Continue using V and H List Boxes to contain your items.

The new type of component seen here is the Col List Box, which contains the names of all the columns of a given data table if you set the first parameter of the Col List Box to All, as in the code below for the first Col List Box, which is housed in the first Panel Box: colListData=ColListBox(All,nLines(min(nc,10))).

To group the buttons and column selection boxes together, use a Line Up Box to align all the elements in two columns.

//the data table you want to operate on
dt = Open( "$SAMPLE_DATA/Birth Death.JMP", invisible(1) );
 
//number of columns in the data table
nc = ncol(dt);
 
//list of methods that will be used for the dropdown menu for "Method"
methodList = {"Average","Centroid","Ward","Single","Complete"};
 
clusterDlg = New Window("Column Selector",/*uncomment if you want a modal window: <<Modal*/,
       BorderBox(left(3),top(2),
              VListBox(
                     TextBox("This UI likes columns more than letters."),
                     HListBox(
                           VListBox(
                                  PanelBox("Select Columns",
                                         colListData=ColListBox(All,nLines(min(nc,10)))
                                  ),
                                  Check Box("Interpolate Missing Values")
                           ),
                           PanelBox("Cast Selected Columns into Roles",
                                  LineupBox(NCol(2),Spacing(3),
                                         ButtonBox("Y, Columns", colListY<<Append(colListData<<GetSelected)),
                                         colListY = ColListBox(nLines(5),"numeric"),
                                         ButtonBox("Ordering", colListO<<Append(colListData<<GetSelected)),
                                         colListO = ColListBox(nLines(1),"numeric"),
                                         ButtonBox("Label", colListL<<Append(colListData<<GetSelected)),
                                         colListL = ColListBox(nLines(1)),
                                         ButtonBox("By", colListB<<Append(colListData<<GetSelected)),
                                         colListB = ColListBox(nLines(1))
                                  )
                           )
                     )
              )
       )
);

 

As a recap thus far, I’ve listed some common components you’ll find yourself needing and their corresponding properties. The comprehensive list of element types and their properties is here.

b = Button Box("text", <script>);
numbox = Number Edit Box(initialValue, <width>));
cb = Check Box ({“item 1”, “item 2”, ...}, <script>);
clb = Col List Box (<Data Table (<name>), <All>, <width(n)>,
<maxSelected(n)>, <nlines(n)>, <script>, <MaxItems(n)),<MinItems(n)>, <character | numeric>, <onChange(expression)>);
comboBox = Combo Box({“item 1”, “item 2”, ...}, <script>); //this is a dropdown menu
h = H List Box(<displaybox args>);
lb = Line Up Box (NCol(nc), <Spacing(pixels)>, displaybox args);
pb = Panel Box (“title”, <displaybox args>);
rb = Radio Box({“item 1”, “item 2”, ...}, <script>);
t = Text Box(“text”);
teb = Text Edit Box (“text”, Hint(“text”));
v = V List Box(<displaybox args>);

Now, we are ready to build a more complex UI.

The script below, which I have annotated (adapted from the example here), creates the following JMP UI and functional program for the Clustering function.

Note that the previous UI examples were not executable, as we were just learning how to build the interfaces. You may have also noticed that the second argument in the Button Box() function was not used. Here, when you click the “OK” button, a script executes. The particular script implemented here is the code for the JMP Clustering function. See the example code to see the function’s script.

 

Example 4: The Clustering functionExample 4: The Clustering function

//the data table you want to operate on
dt = Open( "$SAMPLE_DATA/Birth Death.JMP", invisible(1) );
 
//number of columns in the data table
nc = ncol(dt);
 
//the width of the column list box in pixels
lbWidth = 108;
 
//list of methods that will be used for the dropdown menu for "Method"
methodList = {"Average","Centroid","Ward","Single","Complete"};
 
//what happens upon clicking "Recall" or "Help" buttons
notImplemented = expr(New Window("Feature Not Implemented Yet!",<<Modal, ButtonBox("OK")));
 
//opens new window called "Clustering" that houses all the function display boxes
clusterDlg = New Window("Clustering",/*uncomment if you want a modal window: <<Modal*/,
       BorderBox(left(3),top(2),
              //V List Boxes organize elements vertically, from top to bottom
              VListBox(
                     TextBox("Finding points that are close, have similar values"),
                     //H List Boxes organize elements horizontally, from left to right
                     HListBox(
                           VListBox(
                                  //Column Selection Box
                                  PanelBox("Select Columns",
                                         colListData=ColListBox(All,width(lbWidth),nLines(min(nc,10)))),
                                  //Options Box
                                  PanelBox("Options",VListBox(
                                                //Dropdown with two choices and defaulted to first choice
                                                comboObj=comboBox({"Hierarchical","K-Means"},<<Set(1)),
                                                //Radio Box with five choices and defaulted to third choice
                                                PanelBox("Method",
                                                       methodObj=RadioBox(methodList,<<Set(3))
                                                ),
                                                //Check Box defaulted to checked state
                                                checkObj=check box({"Standardize Data"},<<Set(1,1))
                                         )
                                  )
                           ),
                           //Column Select Boxes Y, Ordering, Label, and By and respective action buttons
                           PanelBox("Cast Selected Columns into Roles",
                                  LineupBox(NCol(2),Spacing(3),
                                         //Y, Columns Button and Column List Box with 5 lines, type numeric
                                         ButtonBox("Y, Columns", colListY<<Append(colListData<<GetSelected)),
                                         colListY = ColListBox(width(lbWidth),nLines(5),"numeric"),
                                         //Ordering Button and Column List Box with 1 line, type numeric
                                         ButtonBox("Ordering", colListO<<Append(colListData<<GetSelected)),
                                         colListO = ColListBox(width(lbWidth),nLines(1),"numeric"),
                                         ButtonBox("Label", colListL<<Append(colListData<<GetSelected)),
                                         colListL = ColListBox(width(lbWidth),nLines(1)),
                                         ButtonBox("By", colListB<<Append(colListData<<GetSelected)),
                                         colListB = ColListBox(width(lbWidth),nLines(1))
                                  )
                           ),
                           //Actions menu
                           PanelBox("Action",
                                  LineupBox(NCol(1),
                                  //OK Button
                                  ButtonBox("OK",
                                         //script that executes upon clicking "OK"
                                         if ((comboObj<<Get)==1,
                                                HierarchicalCluster(
                                                       Y(Eval(colListY<<GetItems)),
                                                       Order(Eval(colListO<<GetItems)),
                                                       Label(Eval(colListL<<GetItems)),
                                                       By(Eval(colListB<<GetItems)),
                                                       Method(methodList[methodObj<<Get]),
                                                       Standardize(checkObj<<get(1))
                                                ),
                                                KMeansCluster(
                                                       Y(colListY<<GetItems)
                                                )
                                         );
                                         clusterDlg<<CloseWindow
                                  ),
                                  //Cancel Button
                                  ButtonBox("Cancel", clusterDlg<<CloseWindow),
                                  TextBox(" "),
                                  //Remove Button
                                  ButtonBox("Remove",
                                         colListY<<RemoveSelected;
                                         colListO<<RemoveSelected;
                                         colListL<<RemoveSelected;
                                         colListB<<RemoveSelected;
                                  ),
                                  //Recall and Help not implemented here, buttons are shown in UI
                                  ButtonBox("Recall",notImplemented),
                                  ButtonBox("Help",notImplemented))
                           )
                     )
              )
       )
);

I hope this tutorial will be useful for JMP users who have wanted to build their UIs to execute scripts, but didn't know where to start. Have you built your own UI in JMP? I’d love to hear your thoughts in the comments.

Last Modified: Sep 9, 2017 12:36 AM
Comments
huifangwang
Staff

I love that you covered how to use the Spacer Box to pad UI elements. Spacing between UI elements is like silence in a sentence, it is very powerful in creating a visually balanced and logically clear UI. Great blog!

nbullen
Level II

The thing that gets messy when I create user interfaces is when I want to initialize the interface so that it runs all of the scripts attached to the various display box functions. This is often the case when I have a radio box that automatically shows the first item as selected and there is another function like a checkbox that is dependent on the radio box selection. Is there an elegant way to do this without having to manually call and set each display box function after the UI part of the script runs?

Craige_Hales
Super User

 @nbullen - Yes, check out App Builder (File->New->Application). Here's a presentation @danschikore did. Here's some doc. App Builder breaks the process of making the displaybox tree into three phases, similar to what you describe: Allocate, Organize, and Initialize. All of the displayboxes are allocated first, then organized into the displaybox tree, then initialized with their defaults. You may never need to look at the App Builder script (and be very careful if you edit it because App Builder can only re-open it in the GUI if App Builder can still understand the script.)