Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Tri-state checkbox

October 19, 2011 5 Comments

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).

CheckBoxTree

Last year, I have already described a built-in Matlab tree control whose nodes have tri-state checkboxes:

a regular MJTree (left) and a CheckBoxTree (right)
a regular MJTree (left) and a CheckBoxTree (right)

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.MIXED (SelectionState also has the SELECTED and NOT_SELECTED values).
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;

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;

Matlab checkboxes displaying mixed states
Matlab checkboxes displaying mixed states

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;

% 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.

Alternative controls

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

% 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

MJCheckBox vs. MWCheckbox
MJCheckBox vs. MWCheckbox

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.

Related posts:

  1. Unorthodox checkbox usage – There are various ways to display interactive split-panes in Matlab GUI. Uiextras flex-panels override a checkbox control's CData to display a divider. ...
  2. Determining axes zoom state – The information of whether or not an axes is zoomed or panned can easily be inferred from an internal undocumented object....
  3. Recovering previous editor state – Recovering the previous state of the Matlab editor and its loaded documents is possible using a built-in backup config file. ...
  4. CheckboxList – Matlab listboxes can be enhanced with checkboxes next to each item. ...
  5. Font selection components – Several built-in components enable programmatic font selection in Matlab GUI - this article explains how. ...
  6. FindJObj GUI – display container hierarchy – The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....
FindJObj GUI Internal component Java JIDE Undocumented feature
Print Print
« Previous
Next »
5 Responses
  1. weiliang November 18, 2011 at 12:20 Reply

    I have tried all three approaches.
    The first one, Modifying the standard Matlab checkbox uicontrol, has little change to my existing code, but the call to findjobj is too expansive and time consuming (i have more than 10 checkboxes).
    Both Displaying as an independent Java control and Alternative controls will have no performance problem. but I have difficulty to add callbacks to the jCheckbox.
    Also all three seem have drawing problem when is in third state (partial check state).
    Can someone comment on this. Code sample for how to add callback to the last two methods is greatly appreciated.

    • Yair Altman November 19, 2011 at 09:04 Reply

      @weiliang – Java controls have some ~30 standard callbacks that you can set, ranging from mouse and keyboard events, through property and hierarchy changes, plus several callbacks that are specific to the control. Try setting the StateChangedCallback and ItemStateChangedCallback. More on Java component callbacks can be found here and in sections 3.4 and 6.4 of my Matlab-Java book.

    • Pecus December 16, 2012 at 09:18 Reply

      @Yair – Thanks for all the advice here! Just discovering all these mysteries…

      I’m having difficulties (probably the same as weilang had) disabling the mixed state of JCheckBox. If it has not been in mixed state, then I can toggle its state and appeareance (selected or deselected) by clicking. But soon as I put it in mixed state, changing the state by clicking does not affect its appeareance.
      Also I could not find the method for setting the state of JCheckBox to selected/deselected. For MWCheckbox it is “jCB.setSelected(1)” (or “0”).
      To put it in a nutshell:
      1. What is the opposite of “jCB.putClientProperty(‘selectionState’, SelectionState.MIXED);”?
      2. What is the counterpart of “jCB.setSelected(1)”?

      Third problem: I wrote a Callback function to switch on or off all subordinated checkboxes, if my JCheckBox has been clicked: (Still only works when not in mixed mode.)

      function Tristatecheckbox_Callback(hObject,eventdata,subCBs) % subCBs as CELL
      isSelected=hObject.isSelected;
      n=size(subCBs);
      for i=1:n(2)
         set(subCBs{i},'Value',isSelected);
      end

      function Tristatecheckbox_Callback(hObject,eventdata,subCBs) % subCBs as CELL isSelected=hObject.isSelected; n=size(subCBs); for i=1:n(2) set(subCBs{i},'Value',isSelected); end

      Now my problem is where/when to associate this function with Java Callbacks.
      I wrote this code snippet, which is working:

      hjCB = handle(handles.jCB,'CallbackProperties'); % initialised with "handles.jCB = javax.swing.JCheckBox(..."
      subCBs={handles.CB1,handles.CB2,handles.CB3};
      set(hjCB,'ItemStateChangedCallback',{@Tristatecheckbox_Callback,subCBs});

      hjCB = handle(handles.jCB,'CallbackProperties'); % initialised with "handles.jCB = javax.swing.JCheckBox(..." subCBs={handles.CB1,handles.CB2,handles.CB3}; set(hjCB,'ItemStateChangedCallback',{@Tristatecheckbox_Callback,subCBs});

      First I put it right after the JCheckBox’s creation, which is in the CreateFcn of a panel. But in CreateFcns there are no visible handles but those of the object in creation, so handles.CB1 can not be allocated.
      For trial&error, I put it in the CallbackFcn of a dummy pushbutton and just clicked this dummy before using the rest, but later I need this snippet to be done before the user can do anything with the GUI.
      3. Is there a function running right after the GUI is created, with access to all the handles? Which one? And if no, where else to put the code?

      Thanks a lot!

      • Yair Altman December 16, 2012 at 10:56

        @Pecus –

        The possible com.mathworks.mwswing.checkboxtree.SelectionState values are: MIXED, NOT_SELECTED and SELECTED, which are pretty-much self-explanatory.

        I assume that you are using GUIDE to create your GUI. In such a case, the *_OutputFcn() function is called after the entire GUI is created, immediately before the control is passed to the user. In this function, you have access to all handles. See this doc-page.

  2. Dhanya Pradeep February 15, 2016 at 11:59 Reply

    Hi Yair,
    I’m trying to use the com.mathworks.mwswing.checkboxtree in my MATLAB application. I’m trying all sorts of methods for handling the actions on enabling and disabling the checkbox node. Unfortunately I’m not getting the right callback to be used for handling the action based on the toggling of the checkbox. Could you give me some hint on the solution.

    Thanks,
    Dhanya

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
ActiveX (6) AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
  • Nicholas (3 days 22 hours ago): Hi Yair, Thanks for the reply. I am on Windows 10. I also forgot to mention that this all works wonderfully out of the editor. It only fails once compiled. So, yes, I have tried a...
  • Nicholas (3 days 22 hours ago): Hi Yair, Thanks for the reply. I am on Windows 10. I also forgot to mention that this all works wonderfully out of the editor. It only fails once compiled. So, yes, I have tried a...
  • Yair Altman (4 days 5 hours ago): Nicholas – yes, I used it in a compiled Windows app using R2022b (no update). You didn’t specify the Matlab code location that threw the error so I can’t help...
  • Nicholas (5 days 1 hour ago): Hi Yair, Have you attempted your displayWebPage utility (or the LightweightHelpPanel in general) within a compiled application? It appears to fail in apps derived from both R2022b...
  • João Neves (8 days 6 hours ago): I am on matlab 2021a, this still works: url = struct(struct(struct(struct(hF ig).Controller).PlatformHost). CEF).URL; but the html document is empty. Is there still a way to do...
  • Yair Altman (11 days 5 hours ago): Perhaps the class() function could assist you. Or maybe just wrap different access methods in a try-catch so that if one method fails you could access the data using another...
  • Jeroen Boschma (11 days 7 hours ago): Never mind, the new UI components have an HTML panel available. Works for me…
  • Alexandre (11 days 8 hours ago): Hi, Is there a way to test if data dictionnatry entry are signal, simulink parameters, variables … I need to access their value, but the access method depends on the data...
  • Nicholas (11 days 22 hours ago): In case anyone is looking for more info on the toolbar: I ran into some problems creating a toolbar with the lightweight panel. Previously, the Browser Panel had an addToolbar...
  • Jeroen Boschma (15 days 5 hours ago): I do not seem to get the scrollbars (horizontal…) working in Matlab 2020b. Snippets of init-code (all based on Yair’s snippets on this site) handles.text_explorer...
  • Yair Altman (43 days 8 hours ago): m_map is a mapping tool, not even created by MathWorks and not part of the basic Matlab system. I have no idea why you think that the customizations to the builtin bar function...
  • chengji chen (43 days 14 hours ago): Hi, I have tried the method, but it didn’t work. I plot figure by m_map toolbox, the xticklabel will add to the yticklabel at the left-down corner, so I want to move down...
  • Yair Altman (51 days 7 hours ago): @Alexander – this is correct. Matlab stopped including sqlite4java in R2021b (it was still included in 21a). You can download the open-source sqlite4java project from...
  • Alexander Eder (57 days 3 hours ago): Unfortunately Matlab stopped shipping sqlite4java starting with R2021(b?)
  • K (63 days 13 hours ago): Is there a way to programmatically manage which figure gets placed where? Let’s say I have 5 figures docked, and I split it into 2 x 1, I want to place 3 specific figures on the...
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top