WOLFRAM LANGUAGE TUTORIAL
Introduction to Control Objects
The Wolfram Language includes many controls and structures related to controls as part of its core language. These control objects are supported in a completely seamless way throughout the Wolfram Language, and can be used anywhere an expression can be used.
These control objects also have a rich option environment, through which their behavior and display can be varied to suit your particular needs. In many cases, the display can be completely taken over by the user, allowing interfaces to be built to arbitrary graphic design specifications.
The function Manipulate is one such interface, which provides a simple and powerful environment for exploring Wolfram Language expressions. In fact, Manipulate was actually written entirely in the Wolfram Language, using control objects and other layout constructs. For many applications, it is perfectly sufficient to just use Manipulate rather than concerning yourself with the low-level control objects or with this tutorial. But if you have an application in mind that is not satisfied by an existing framework, there is no substitute for using the control objects directly.
Note that this tutorial will not discuss matters already covered in "Introduction to Dynamic", so it is suggested that you familiarize yourself with that tutorial first before proceeding with this one.
Arguably the simplest control, the button control links a mouse click to a single action. The first argument to Button is the label that will be displayed on the button's face, and can be any Wolfram Language expression, including graphics or typeset objects. The second argument is the function that will evaluate when you click the button. The evaluation takes place in the kernel, and the output of this evaluation is typically not seen unless it produces some side effect.
Here is a simple button that increments a variable, along with a dynamic display of the value of that variable, so you can see the effect of clicking the button.
Any evaluation that the Wolfram Language can do can be done by a button. And that evaluation happens when the button is clicked, not when the button is created. (See the documentation for the attribute HoldRest for the technical details of how this is done.) But remember, the output of that evaluation is not shown as it is for Shift+Return evaluation. So unless the button's function has a visible side effect, you may think the button is not doing anything, when in fact it is just not showing you that it is doing anything. Here are two buttons that perform identical actions, except that one of them makes the result visible in a new palette window, while the other merely does the requested evaluation silently.
When building an interface, you may want to adjust details of the button's appearance. This is managed with the Appearance option to Button. The Wolfram Language provides several built-in appearances for buttons, including and for platform-standard palette buttons, and for dialog box buttons, the default.
It is important to point out that the default Wolfram Language appearance of buttons and other controls is taken directly from the underlying operating system. So a control's appearance will be different on Windows than on Macintosh. For instance, dialog box buttons on Macintosh are designed to never be smaller than some minimum size.
There are other built-in appearances, as well as None, which draws no frame around your button. This can be useful if you want the button to have a completely custom appearance, which you would then specify yourself in the first argument for Button.
Here is a very simple interface created from buttons that have Appearance->None. Click one of the squares to change the color of the circle. Notice one problem with using buttons that have no recognizable frame is that users might not know that they are buttons at all. In this case, it is up to you to create an appearance that is obviously clickable.
There are a few more options to Button that you may find especially useful. The Enabled option, for instance, indicates whether a button should accept mouse clicks or not. If Enabled is set to False, the button will be dimmed and will ignore mouse clicks.
Enabled is most often used in conjunction with Dynamic, so that the button accepts clicks as long as doing so makes sense, and then it stops. For example, if you look back at the increment button from above, you might want to impose a maximum value. Once that maximum value is attained, the setting for Enabled can automatically become False, and the button will then be dimmed. For completeness, add a decrement button too, which stops at a minimum value, and wrap the whole thing in a DynamicModule to isolate the variables.
If you regularly use more than one kernel, or want to create buttons that use the front end directly, then you will want to know about the Evaluator option. This can be set to the name of any kernel, or Automatic (the default) which means to use the current default kernel. The setting Evaluator->None will cause actions to take place entirely within the front end if possible. See FrontEndExecute for details.
When using Button inside of Grid or Column, another option you should know about is ImageSize. By default, buttons will stretch in all directions to fill that element of the grid. This is due to the default setting of ImageSize, namely Full. Here is a slight modification of the example above that shows that the buttons automatically resize when the Column they are in becomes wider.
To override this behavior, use a different setting for ImageSize, such as Automatic, which allows the buttons to remain their fixed, natural size. You can also use a fixed ImageSize to specify the button's dimensions in printer's points.
The last of the options for Button you will look at is Method. Method determines the way in which the button communicates with the kernel. With the default setting of , clicking the button will cause the evaluation to be sent to the kernel over the preemptive link. See "Advanced Dynamic Functionality" for details on the preemptive link. That is the same link used for dynamic evaluation. Such buttons will respond to user clicks immediately, even if the user is also running some long Shift+Return evaluation on the main link.
Here is a simple example to illustrate the power of this setup. First, initialize a variable and display a preemptive button that changes the variable's value.
Next, use Shift+Return to evaluate this While command.
Under normal circumstances, the only way out of this While loop would be to abort the calculation. But since the button above is communicating with the kernel on a different link, it is not blocked by this While loop. Clicking the button will initiate a preemptive evaluation that changes the value of the variable, which in turn causes the While loop to end.
One important consequence of using Method->"Preemptive" is that button evaluations are subject to the same timeout period as other dynamic evaluations, specified using the front end DynamicEvaluationTimeout option. So if you have an evaluation that you expect will take more than a couple of seconds to evaluate, you should use Method->"Queued". Clicking such a button will use the main link when evaluating its function, and that evaluation will be queued along with evaluations queued using Shift+Return.
For instance, the buttons in the very large output suppression panel use Method->"Queued", since handling very large outputs can require a considerable length of time.
The Button control is quite flexible and powerful, but there are a couple of common variations that warrant having their own, simple functions for generating them.
PasteButton creates a button that performs a paste operation. Hyperlink creates a button that will jump to a given URI. FileNameSetter creates a button that brings up a system file picker dialog, and then remembers the path to the chosen file. ColorSetter creates a button that will bring up a system color picker dialog.
ActionMenu, which is discussed in the section "PopupMenu and ActionMenu", also performs a function similar to Button. It allows the aggregation of multiple actions into a collection of menu items, each of which has an individual function that is executed exactly as the function of a Button is executed.
Most other controls have a somewhat different purpose, namely to associate themselves with a variable. The example of sliders, which will be discussed next, is shown in some detail in "Introduction to Dynamic". Almost all of the remaining controls detailed in this tutorial share this feature with sliders. Their main purpose is to display the current value of a variable, and to set the value of that variable when that control is used.
Such controls all have the same basic syntactic form:
where control is the name of the control, var is the variable the control will be changing, domainSpec is the optional specification for the space over which the control will work, and opts are options affecting how the control acts and looks.
Controls also all interact with the kernel over the preemptive link, and so are subject to the same timeout period as buttons with Method->"Preemptive" as described in "Introduction to Control Objects", as well as other dynamic displays. This reinforces the notion that controls should only be used to control things that happen quickly. It makes no sense to have a slider initiate evaluations that may take minutes or hours to run. As with buttons though, there are ways to avoid this timeout, which will be looked at later on.
There are a handful of sliders that are available in the Wolfram Language. The simplest one is a horizontal slider that allows you to choose any number between 0 and 1. Here, attach the slider to the variable and add a dynamic display of this value so you can immediately see the slider's effect.
Basic use of Slider is covered rather thoroughly in "Introduction to Dynamic", but there are a couple of uses that are slightly uncommon. For instance, you can slow down your slider drags by holding down modifier keys. Details about this feature can be found in "Introduction to Manipulate".
You can also use a slider to choose among a set of discrete values instead of continuous values. Here are four sliders, each of which allows you to select certain items between 0 and 10. The first is a continuous slider that selects a real number; the second is an integer-valued slider; the third uses a rational step size to visit all multiples of 1/3; and the fourth slider demonstrates the ability of Slider to range over a discrete set of specified objects, which might be integers, real numbers, or any other expression, in any order.
Notice that the position of a slider's thumb will always try to represent the value of the underlying variable. If the variable's value is not accessible on that slider, the thumb will move to one end of the slider and its background will turn a shade of red to indicate that the value is out of range.
Like Button, Slider has many options for changing its appearance and its use. The Appearance option determines, among other things, the size and shape of the slider thumb. Here are some of the built-in variations, some of which require the slider to change its orientation. (Note that the sliders are drawn by the operating system, and of course each operating system supports a slightly different set of appearances. If a slider appearance is not supported by your operating system, the default appearance will be used.)
VerticalSlider is also available, which automatically sets Appearance->"Vertical".
Enabled and ImageSize are not discussed again for Slider or all other controls, but they work throughout in exactly the same way. The only difference is that ImageSize->Full is only supported by Button, and not other controls. However, Slider and the rest do support both symbolic and fixed numeric image sizes.
Notice that the appearance changes automatically for the different ImageSize settings. That is because the default setting for the Appearance setting is Automatic. If you want to combine an ImageSize with a different Appearance for some reason, you can do that, too. Here, ask for components to draw at their medium size, while constraining the overall size to be tiny.
Here is a good place to point out an interesting variation on Slider. The Manipulator control has exactly the same syntax as Slider, but adds an input field and animation controls to its display. These are collapsed by default. Click the
icon to expose them. (How to create input fields and animation controls separate from Manipulator
will be shown shortly.)
You can also reveal the animation controls automatically by specifying Appearance->"Open".
Manipulator supports a unique setting for Appearance, , which displays the usual constellation of controls along with a frameless input field outside the hidden area. Seeing and setting the value of the variable in this way can be quite convenient.
IntervalSlider is a special kind of slider that allows the setting of two points on a range, typically thought of as an upper bound and a lower bound. The value of IntervalSlider is a list of the two endpoints.
This slider has three thumbs that can be manipulated. The upward pointing thumb on the left controls the lower value and the downward pointing thumb on the right controls the upper value. The space in between serves as a third thumb to move the entire interval.
Since there are two sliders, this raises some possibilities for what happens if you attempt to move the slider at one end of the interval past its opposite slider. The default behavior is to allow the user to do this, and represent it by flipping the order of the lower and upper bounds in the value.
Another possibility is to prevent the ranges from being flipped entirely. This can be done using the Method option. Method->"Stop" causes the left slider thumb to serve as an absolute stopping point for interactive manipulation of the right slider thumb and vice versa:
Method->"Push" allows the slider thumb in use to push the other one out of the way. For example, try dragging the right-hand slider thumb all the way to the left below.
Animator, Trigger, and ProgressIndicator
Animations are another important feature of the Wolfram Language, and Animator is the name of the control used to manage them. The job of an Animator control is to automatically push the value of a variable through a given domain. Here is an Animator that runs the value of from 0 to 1. When it gets to the top of the domain, it wraps around and starts again at the bottom.
As you can see, the Animator control has several different elements in its display, known as AppearanceElements. There is the slider, which shows the current value of the variable (known as the ); the "-" and "+" buttons, which move the value a small amount to the left or right ( and ); the button that toggles whether the Animator is playing or paused (); and buttons to control the speed () and direction () of the animation. You can change the AppearanceElements option to include only some of these, based on your current needs. Here is the same animation but with the Animator displaying only a play button.
In addition to showing controls for each of these aspects of an animation, Animator provides options to set the initial state of these controls. AnimationRunning lets you start up an animation in a paused state. AnimationDirection lets you set the initial direction of an animation. DefaultDuration and AnimationRate let you determine the speed of an animation (more about those in a minute).
Animator supports all the same domains that Slider does in its second argument, namely , , and . In addition, Animator also supports max being Infinity and min being -Infinity.
One important thing to keep in mind with animators is that, like other dynamics, they are only active while they are actually visible on the screen. If an Animator is in a closed cell group, scrolled off-screen, or in some other hidden location, then it will not be actively changing the underlying variable. If you are using the online version of this document, opening the cell group below will cause the value of y to begin changing.
Now back to duration. There are several ways to control how fast an animation runs. By default, an animation will run fast enough so that it gets from the start of its domain to the end in about five seconds. This time is determined by the DefaultDuration option. Here are two animators that use this option, one of which runs twice as fast as the other.
Instead of specifying the overall duration, you can specify how fast the animation runs in units per second via the optional third argument of Animator, which is a convenient argument for setting the AnimationRate option. This is especially useful for infinite animations, since setting the overall duration for an infinite animation would be meaningless.
Note that DefaultDuration and AnimationRate are two ways to ultimately specify the same thing, namely how fast an animation is running. By default, AnimationRunning is set to Automatic, which indicates that the DefaultDuration option should be respected. If AnimationRate is set to anything else (e.g. if you put a number in the third argument of Animator), then DefaultDuration will be ignored.
Independent of DefaultDuration and AnimationRate, another thing you can specify is RefreshRate, which specifies how many times per second the Animator should change the value of the variable. By default, Animator runs as fast as possible, which will constantly require CPU time. By setting a lower RefreshRate, the kernel will have more time available to other evaluations. Here are three animators that use three different refresh rates. Every one of these animators still takes about five seconds to get from the minimum to the maximum, but those with the lower refresh rates will show fewer values over the course of the animation.
The DisplayAllSteps option also overrides DefaultDuration and AnimationRate if necessary. When this is set to True, every element of a discrete domain is visited by the animation, regardless of whether it can do so in the time allowed.
When using Animator to animate through a list of elements, there is a syntax for specifying relative frame durations for each individual frame. Instead of providing a list of frames , replace each element with the pair , where is the relative duration of the corresponding element.
Lastly, AnimationRepetitions is an option that indicates how many times to run through the animation before automatically stopping. The default is to cycle through the animation indefinitely, indicated by AnimationRepetitions->Infinity, but it can be set to any finite value. Here is an Animator that runs twice through and then stops.
In fact, Trigger is a variation of Animator dedicated to pushing a variable through its domain once and then stopping. Trigger is intended for animations that should always be started from the beginning. Thus, Trigger has a pause button, but there is no unpause button. There is also a reset button, and of course the main trigger button.
Another control that is quite similar to Slider and Animator is ProgressIndicator. As the name implies, ProgressIndicator will show a platform-standard progress indicator, drawn as a kind of thermometer on most platforms. Its syntax is identical to Animator and Slider, and the value it displays is communicated via dynamic variables, just like other controls. Here, simulate a time-consuming evaluation with Pause, with an accompanying progress display.
For indeterminate computations where a thermometer is not appropriate, you can specify infinite limits to ProgressIndicator, and it will display an indication that something is happening, without any indication of when it might finish.
There is also a higher-level function, Monitor, that can be used in cases like this. Monitor can display anything as the monitoring expression, but a ProgressIndicator is especially useful. Note that using Monitor also has the very nice feature that the monitoring expression is removed automatically when the evaluation of the first argument is finished.
Slider2D and ColorSlider
These one-dimensional slider-like controls are useful, but what if you want to control something that is fundamentally a two-dimensional piece of data, like the coordinates of a point? For that purpose, you have Slider2D, which lets you move a slider thumb anywhere in a given area.
Slider2D has the same basic syntax as Slider, except that the min and max are each allowed to be a pair of numbers instead of a single number. An optional step size can also be given.
Like all controls, Slider2D takes options like Enabled and ImageSize. ImageSize is especially convenient here to change the aspect ratio of the slider to match the aspect ratio of the data.
Another slider that moves through a two-dimensional space is ColorSlider, which allows you to choose a color by clicking and dragging on a color gradient to the right. You can also open your system's color chooser dialog by clicking on the solid colored square at the left of the ColorSlider.
Checkbox and Other Toggling Controls
If you want a single control to cycle the value of a variable through two or more values, then you most likely will use Checkbox or Toggler. Here is a very simple example that shows how Checkbox[Dynamic[var]] toggles the value of the variable var between True and False.
With its optional second argument, you can have checkbox cycle through not just True and False, but any list of values. Using Shift+ Click will go to the previous value. Here you cycle through other possible settings for plot axes using Checkbox. A DynamicModule has been added to isolate this example from the previous one.
Despite being able to customize the values taken on by a checkbox, you cannot customize its display at all. Toggler is a generalization of Checkbox, which also lets you specify a completely custom display for your toggling control.
Finally, there are conveniences for constructing a set of checkboxes or togglers all at once. TogglerBar presents the controls arranged in an actual bar of buttons, while CheckboxBar provides a set of labeled checkboxes. The value of the variable in these cases is taken to be the list of items that are currently checked, or toggled, in click order.
Of course, once you start specifying a set of controls with a set of labels, several questions arise about exactly how they are laid out. You can set Appearance to , , or for CheckboxBar and TogglerBar, to get different layout and word-wrapping behaviors.
The Opener control is another variant of Checkbox, which instead of displaying a box with or without a checkbox, displays a disclosure triangle that points right or down. The value assigned to the variable is a Boolean, just like Checkbox.
This academic example does not make much visual sense however, since the display of the Opener control leads you to believe something should be appearing under it. The primary use of Opener is actually in OpenerView, which provides this vertical layout automatically by internally using Opener together with PaneSelector and Grid.
For details on OpenerView and other view objects, please see "Views".
RadioButton and Other Setting Controls
Another useful interface construct is the radio button, which allows users to choose exactly one element out of a set. RadioButton is the Wolfram Language function that creates a radio button. Here is a radio button which, when selected, will set x equal to .
Of course, one radio button by itself is not very useful. Once you click it there is no way to unclick it, and clicking it again will have no effect. Connecting two or more radio buttons to the same variable will have the usual, choose-one-from-many effect that distinguishes radio buttons as interface elements.
Now, a set of radio buttons is not much good without labels. By the time you specify all radio buttons based on the same variable, and all the labels, there is quite a lot of redundancy. The Wolfram Language provides a function, RadioButtonBar, that will create a set of radio buttons all tied to the same variable. You can specify labels for each radio button, with the default labels being the values themselves.
For more complicated interfaces, it is sometimes useful to have the choose-one-from-many behavior of a radio button, but with the flexibility of providing a completely custom display. For that purpose, you have the Setter construct. By default, a setter just looks like a button that appears either pressed or not in the same situations as a radio button would appear selected or not.
Again, there is a convenience for creating a collection of setters all tied to the same variable: SetterBar. SetterBar uses a different default setting for the Appearance option to Setter, and so its appearance may be different on different platforms. Given its default appearance, you can think of SetterBar as a disembodied TabView control.
Here is an example that uses graphical labels for the setter bar.
Note that RadioButtonBar and SetterBar accept the same Appearance settings of , , and that CheckboxBar and TogglerBar do.
PopupMenu and ActionMenu
You have seen how to create and use radio buttons. But when there are more than just a few radio buttons, they can become quite awkward to use. Another control that lets you choose one element out of a set is the popup menu. The PopupMenu function has exactly the same syntax as RadioButtonBar and SetterBar and provides the same functionality, except with a different interface.
PopupMenu can also take the symbol Delimiter in place of an item, which will draw a rule between two items. This is useful for visually grouping like elements. Just like a system popup menu, the delimiter cannot be selected or displayed in the collapsed popup menu.
The syntax also allows you to separate the value assigned to the variable from the display in the menu. For example, here is a menu that associates numbers with the variable , but that displays actual words on the menu.
Notice that once you choose something from a popup menu, the popup menu will remember your choice. Not only is it displayed in the collapsed popup menu, but on some platforms it is also marked with a check mark when the menu is expanded or popped up.
To further customize a popup menu, you can specify a label to display if the value of the dynamic variable is not one of the values listed in the second argument. You do so via the optional third argument.
Finally, the fourth argument can specify an arbitrary display for the PopupMenu when no one is clicking on it. Using the fourth argument will prevent the menu from drawing any of the system-specific hints that it would otherwise use, like a control frame or color, so it is up to the developer to make the user want to click on the custom display.
There is another kind of menu whose purpose is not to provide a radio button-like choice, but rather to perform the action associated with the selected item. In the Wolfram Language, this construct is known as ActionMenu. You can think of ActionMenu as a sort of multi-button that evaluates one of several functions depending on which menu item you choose. It also has some of the same caveats as were discussed for Button, such as its action's being effectively invisible except for side effects.
Note that the syntax for ActionMenu uses RuleDelayed () to prevent the actions from evaluating until they are actually chosen by the user. That means that, unlike PopupMenu, specifying labels is not optional for ActionMenu—they are an integral part of the syntax.
ActionMenu also has an Appearance option that can be used to change the overall display of the menu. Here is a simple Manipulate that demonstrates some of the more useful appearances.
Finally, note that ActionMenu takes the same Method option Button uses to determine how to evaluate its actions. With the default option setting Method->"Preemptive", the action will be evaluated immediately, but will be aborted if the evaluation requires more time than is specified by the DynamicEvaluationTimeout option. An ActionMenu with actions that will take a noticeable length of time should instead use the option Method->"Queued" to specify that the evaluation should be put into the regular evaluation queue and allowed to run to completion.
The InputField control is unique in that it allows the user to enter any expression at all into it. In its simplest form, it just associates the given expression with the specified dynamic variable.
However, InputField also has a unique set of problems associated with it. For instance, depending on your application, you may want an input field that allows only numbers, only strings, or arbitrary typesetting or expressions. There are a couple of ways to do that. The easiest way is to specify one of the predefined types for InputField in its second argument. Input fields of type Number do not allow typing anything except characters you would find in a number.
Note that arbitrary expressions can take up arbitrarily much screen real estate, and InputField by default will grow to accommodate it. The FieldSize option lets you specify a minimum and maximum size for both the horizontal and vertical dimension of an InputField. By default, an InputField is restricted to be exactly 20 ems wide, but as tall as it likes.
Another option that is more relevant for InputField than most other controls is ContinuousAction. By default, InputField does not commit to its new value until you press the Enter or Tab key. However, for an InputField of type Number, String, and Boxes, you can set ContinuousAction->True to automatically commit to the new value after every key press.
With ContinuousAction->True, you can also use the second argument of Dynamic as described in "Introduction to Dynamic" to specify your own filters for what characters a user is or is not allowed to type. For instance, this InputField uses ToUpperCase to coerce its input to upper case.
Finally, here is a simple example that builds a new control that combines a frameless input field and a popup menu.