When presenting information visually in graphical user interfaces (GUIs), we often need to present and enable interaction with state data (such as On/Off). In most cases, we would naturally use a checkbox to present the information and enable interaction. But What can we do if the data has three possible states. For example, Yes/No/Maybe, or: Full/Empty/Partial, or: Up/Down/Undetermined ?
Until today, Matlab GUIs had to resort to using drop-down (aka combo-box or popup-menu) or radio-button controls to present such information. However, would it not be nicer if we could still use a checkbox? Outside Matlab, such a control is known as a tri-state checkbox and many modern GUI frameworks support it. Well, surprise surprise, so does Matlab (although you would never guess it from the documentation).
Last year, I have already described a built-in Matlab tree control whose nodes have tri-state checkboxes:
Today I will show how we can use these checkboxes as independent GUI controls.
Modifying the standard Matlab checkbox uicontrol
In order to modify the standard Matlab checkbox uicontrol, we need to first get its underlying Java component reference. This is done using the findjobj utility. We then update its UI wrapper to be the same as the
CheckBoxTree‘s checkbox control.
To programmatically set a mixed state we update the ‘selectionState’ client property to
SelectionState also has the
Here is an end-to-end example:
hCB = uicontrol('Style','checkbox', ...); jCB = findjobj(hCB); jCB.setUI(com.mathworks.mwswing.checkboxtree.TriStateButtonUI(jCB.getUI)); % Update the checkbox state to MIXED newState = com.mathworks.mwswing.checkboxtree.SelectionState.MIXED; jCB.putClientProperty('selectionState', newState); jCB.repaint;
Displaying as an independent Java control
Instead of retrofitting a standard Matlab uicontrol as described above, we can directly use the standard
javax.swing.JCheckBox which does not normally support tri-state (it only has two states), displaying it in our GUI with the built-in javacomponent function:
% Display the checkbox (UNSELECTED state at first) jCB = javax.swing.JCheckBox('JCheckBox - mixed',0); javacomponent(jCB, [10,70,150,20], gcf); % Update the checkbox state to MIXED import com.mathworks.mwswing.checkboxtree.* jCB.setUI(TriStateButtonUI(jCB.getUI)); jCB.putClientProperty('selectionState', SelectionState.MIXED); jCB.repaint;
Note that instead of using
javax.swing.JCheckBox, we could use the internal Matlab class
com.mathworks.mwswing.MJCheckBox, which directly extends
JCheckBox and adds mnemonic (shortcut-key) support, but is otherwise fully compatible with
JCheckBox. Actually, it is
MJCheckBox which is the underlying Java component of the standard Matlab checkbox uicontrol.
Now that we have seen that Matlab includes built-in support (well, at least support in the technical sense, not the official customer-support sense), would you be surprised to learn that it includes similar support in other internal components as well?
The internal Matlab class
com.mathworks.mwt.MWCheckbox directly supports a tri-state (yes/no/maybe) checkbox, without any need to update its UI, as follows:
% Display the checkbox (UNSELECTED state at first) jCB = com.mathworks.mwt.MWCheckbox('MWCheckbox - mixed',0); javacomponent(jCB, [10,70,150,20], gcf); % Update the checkbox state to MIXED jCB.setMixedState(true); % Retrieve the current state isMixedFlag = jCB.isMixedState(); % true/false
Note that the State property, which controls the standard selected/unselected state, is entirely independent from the MixedState property. Both State and MixedState are boolean properties, so to get the actual checkbox state we need to query both of these properties.
Another internal Matlab class that we can use is JIDE’s
com.jidesoft.swing.TristateCheckBox (which is pre-bundled in Matlab and is fully documented here).
There are many other tri-state checkbox alternatives available online (for example, here, here and here). We can easily include them in our Matlab GUI with the javacomponent function. Using external components we can be more certain of the compatibility issues in past and future Matlab releases. On the other hand, internal Matlab classes do have the advantage of being inherently accessible on all platforms of the same Matlab release, whereas non-Matlab components must be included in our deployment package.
Do you use any tri-state controls, either Matlab or external, in your work? If so, please share your experience in a comment below.