- Undocumented Matlab - https://undocumentedmatlab.com -

Editable combo-box

Posted By Yair Altman On October 9, 2013 | 20 Comments

In previous articles, I explained how we can use findjobj [1] to customize a Matlab uicontrol’s underlying Java control, thereby improving its appearance and functionality. My two previous articles [2] on the Matlab editbox were a classic example of this mechanism. Unfortunately, this technique does not always work well, and an alternative mechanism needs to be used. One such case in point is the subject of today’s article.
Matlab combo-box (a.k.a. “popup-menu” or “drop-down”) controls are very simple controls that accept a list of strings from which a user can select. This is a very simple control that answers a wide range of use-cases. Unfortunately, it is quite limited. Among other limitations, we cannot modify the popup-panel’s appearance/functionality; we cannot select multiple items; and we cannot type-in a value in the control’s editbox. Today’s article will focus on the latter limitation, namely how to use an editable combo-box.

Trying to make Matlab’s standard combobox editable

We can indeed use findjobj to get a Matlab combo-box’s underlying Java control. This turns out to be a com.mathworks.hg.peer.ComboboxPeer$MLComboBox object, which extends the standard Java Swing JComboBox [3]:

>> hCombo = uicontrol('Style','popup', 'String',{'a','b','c'});
>> jCombo = findjobj(hCombo)
jCombo =
	javahandle_withcallbacks.com.mathworks.hg.peer.ComboboxPeer$MLComboBox

This jCombo control has the Editable property that we can then try to override (the default value is false):

>> jCombo.setEditable(true);
>> jCombo.Editable = true;          % equivalent alternative
>> set(jCombo,'setEditable',true);  % equivalent alternative

Editable combo-box control
Editable combo-box control

The bad news is that the moment we enter some value (as in the screenshot here) that is not already a member of the pop-up panel (i.e., the cell-array in the String property), then the control disappears and a warning message is issued to the Matlab console:

Warning: popupmenu control requires that Value be an integer within String range
Control will not be rendered until all of its parameter values are valid
(Type "warning off MATLAB:hg:uicontrol:ParameterValuesMustBeValid" to suppress this warning.)


The reason for this behavior is that when the combo-box object detects that the text field’s content match none of the popup list items, it automatically sets jCombo‘s SelectedIndex to -1 and Matlab’s corresponding HG Value property to 0. At this point the Matlab implementation kicks in, hiding the uicontrol since it considers 0 an invalid value for the Value property. This is similar to the check being done to test for an empty HG String value (=no items):

>> set(hCombo, 'string', [])
popupmenu control requires a non-empty String
Control will not be rendered until all of its parameter values are valid.

We can clear these particular warnings via:

warning('off','MATLAB:hg:uicontrol:ParameterValuesMustBeValid')

but this does not prevent the control from being hidden – it just prevents the warning from showing on the Command Window.
We can dive deeper and try to modify the underlying data model and disassociate the Java control from HG, but let’s stop at this point since there is really no point considering the fact that there is a much simpler alternative.
Note: if you do decide to make the standard Matlab uicontrol editable, read here [4] for a related customization that I posted several years ago.

The pure-Java alternative

Rather than customizing Matlab’s uicontrol, we can easily create an identical-looking control using the standard Java Swing JComboBox, which has none of these problems/limitations. We can create and display the component in one go using the semi-documented javacomponent [5] function:

position = [10,100,90,20];  % pixels
hContainer = gcf;  % can be any uipanel or figure handle
options = {'a','b','c'};
model = javax.swing.DefaultComboBoxModel(options);
jCombo = javacomponent('javax.swing.JComboBox', position, hContainer);
jCombo.setModel(model);
jCombo.setEditable(true);

We can use a variant of javacomponent to create the component with the model in one go, replacing the highlighted lines above:

jCombo = javacomponent({'javax.swing.JComboBox',model}, position, hContainer);

Once we have the control ready, all we need to do is set its ActionPerformedCallback property to our Matlab callback function and we’re pretty-much set. We can get the currently-selected text using char(jCombo.getSelectedItem) and the selected list index (0-based) using jCombo.getSelectedIndex (which returns -1 if we entered a non-listed value, 0 for the first list item, 1 for the second etc.). More information can be found here [6].

Lesson learnt

In the past 20+ years of my professional life as engineer and development manager, my number one rule has always been [7]:

DON’T FIX IT, IF IT AIN’T BROKE!

But sometimes, we should also remember an alternative version:
DON’T FIX IT, IF IT’S EASIER TO REPLACE!

Available report – “Advanced Customizations of Matlab Uicontrols”

Interested readers can find more information about these and other possible customizations in my report on “Advanced Customizations of Matlab Uicontrols“. This 90-page PDF report can be purchased here [8] ($29, please allow 24 hours for delivery by email). The report explains how to customize Matlab’s uicontrols in ways that are simply not possible using documented Matlab properties. This includes treatment of push buttons, toggle buttons, radio buttons, checkboxes, editboxes, listboxes, popup menus (aka combo-boxes/drop-downs), sliders, labels, and tooltips. Much of the information in the report is also available in hard-copy format in chapter 6 of my Matlab-Java programming book [9].

Categories: GUI, Java, Low risk of breaking in future versions, Semi-documented function, UI controls


20 Comments (Open | Close)

20 Comments To "Editable combo-box"

#1 Comment By moshe On February 20, 2014 @ 01:48

shalom Yair,
first of all – I enjoy your fruitfull and interesting ideas
second, regarding the editable combobox – is there a way to search the list as one types the words ‘online’ so he needs not scroll the whole list. i have a list of over 3000 to search…

best
moshe

#2 Comment By Yair Altman On February 20, 2014 @ 02:23

@Moshe – you can either update the combo’s list items in the control’s KeyTypedCallback, or use a dedicated control that does it for you. One example is Matlab’s internal com.mathworks.widgets.AutoCompletionList, but this component does not exist in all Matlab releases.

strs = {'This','is','test1','test2'};
strList = java.util.ArrayList;
for idx = 1 : length(strs),  strList.add(strs{idx});  end
jPanelObj = com.mathworks.widgets.AutoCompletionList(strList,'');
javacomponent(jPanelObj.getComponent,[10,10,200,100],gcf);

AutoCompletionList

I explain this and other alternatives in pages 296-297 and 407-416 of my book.

#3 Comment By moshe On February 23, 2014 @ 02:27

shalom Yair,
as i struggle with the AutoCompletionList, a few questions are arised:
1. how do i retrieve the value, string one chooses?
2. can it be modified to look and behave like combobox?

looking forward to hearing from you…
moshe

#4 Comment By moshe On February 23, 2014 @ 02:47

another questions
is there a way to search with wild cards and make the list shorter, as the user types the search?

#5 Comment By Yair Altman On February 23, 2014 @ 15:17

@Moshe – I do not have additional information to what I wrote above and in my book. I’m afraid that you will need to investigate this by yourself for the time being, since I do not plan to write an article about this in the foreseeable future, sorry.

#6 Comment By moshe On March 11, 2014 @ 19:42

I succeeded thanks to your suggestion to make use of the various optional Callbacks, when i’m done with the code i’ll be glad to publish it here

#7 Comment By Steven Tsai On September 3, 2014 @ 20:28

Hi, Yair,
“you can either update the combo’s list items in the control’s KeyTypedCallback”
I tried set the jCombo’s KeyTypeCallback property, but it does not work:

position = [10,100,90,20];  % pixels
hContainer = gcf;  % can be any uipanel or figure handle
options = {'a','b','c'};
model = javax.swing.DefaultComboBoxModel(options);
jCombo = javacomponent('javax.swing.JComboBox', position, hContainer);
jCombo.setModel(model);
jCombo.setEditable(true);
jComboh = handle(jCombo,'CallbackProperties');
set(jComboh,'KeyTypedCallback','disp(''Hello, Yair'')')

could you explain more details, thanks so much.

#8 Comment By Yair Altman On September 4, 2014 @ 01:42

@Steven – You need to specify the KeyTypedCallback on the combo-box’es editbox (text-field) sub-component, not on the top-level component. Namely:

jComboField = handle(jCombo.getComponent(jCombo.getComponentCount-1), 'CallbackProperties');
set(jComboField, 'KeyTypedCallback', @myCallbackFunc);

#9 Comment By Steven Tsai On September 3, 2014 @ 02:13

Hi Yair,

I was trying to use a ◾TreeComboBox in my GUI, but it seems something is wrong:

#10 Comment By Yair Altman On September 3, 2014 @ 02:16

What’s wrong exactly?

#11 Comment By King On September 15, 2014 @ 12:16

Hi Yair

Firstly, thank you for your website.
I found a lot of useful hints from your website.

At this time, I try to call a MATLAB function when an item was selected in combo box’s drop down list. (mouse or up/down key pressed)
I know I can do that in Java by adding ‘addactionlistener’ or ‘additemlistener’.

How can I do the same job in MATLAB GUI?

Thanks,

King

#12 Comment By Yair Altman On September 15, 2014 @ 13:51

@King –

set(jCombo, 'ActionPerformedCallback', @myCallbackFcn)

#13 Comment By King On September 15, 2014 @ 20:21

Thanks! It works!
Before I saw your solution, I figure out I can use KeyReleasedCallBack as my callback property
However, it still not solve the mouse click issue.
Your one get the job done perfectly!
Furthermore, instead of clicking mouse on the item, moving mouse on item then fire the callback?
I tried jCombo.getcomponent(2) and added mouselistener, but it doesn’t help.
Maybe I am in a right approach but missing some lines?

Thanks!

#14 Comment By King On September 24, 2014 @ 07:51

Hi Yair

set(jCombo, ‘ActionPerformedCallback’, @myCallbackFcn)

This commandline can handle the callback.
But I want to handle the user input more precisely.
I try to hear ‘Up’ ‘Down’ ‘Enter’key pressed or mouse left click.
Therefore, I can assign different function to different user input.
Is it possible to do that in combo box? If so, how?

Thanks a lot.

#15 Comment By Yair Altman On September 27, 2014 @ 12:27

@King – see my [16] to Steven Tsai.

#16 Comment By Buer On December 3, 2014 @ 01:43

Hi Yair,

Thanks for the great information. However I want to ask if I have two combobox, how can I put them inside one figure instead of two?

Meanwhile, if I want to have a label for each combbox. How can I do that? I checked around, did not find anything about that.

Thanks.

#17 Comment By Yair Altman On December 3, 2014 @ 15:13

@Buer – you can use the Position property of the uicontrol to place it anywhere in your figure, and place separate uicontrols in separate locations. You can use other calls to uicontrol to place text labels. Look it up in the [17].

#18 Comment By Eric On August 11, 2017 @ 20:31

I created a plotter using three popup menus: one for X-variable, one for Y, and one for a figure name. When a figure name (number) is selected, its callback function grabs strings from X and Y popup menus, search these from a loaded dataset, and plots them.

What I want to do is multiple-selection on a popup menu. I researched quite a bit and learned that popup menu doesn’t have that capability as you also mentioned on the top in the regular documented way.

The reason why I don’t want and almost can’t use list box is my GUI has many panels from top to bottom; each containing the three popup menus mentioned above. Each panel represents one dataset. This means if I select and load ten .MAT files, a GUI will be created with 10 panels from top to bottom. Each dataset can have as many as 100 or more variables. Unless I completely scrub the current GUI generation code, listbox won’t work. Say each listbox shows ten variables and a scroll bar. The height of it and some margins above and below times 10 will create a gigantic GUI that will be basically unusable.

Do you know a work-around? Thank you in advance.

#19 Comment By Yair Altman On August 12, 2017 @ 20:44

@Eric – you can integrate a com.jidesoft.combobox.MultiSelectListComboBox or MultilineStringComboBox. If you need consulting assistance, contact me by email.

#20 Comment By Amit On November 6, 2017 @ 17:44

Hi Yair,

How can I use JIDE’s DateComboBox as the celleditor for a column in a jide table? So basically a table column having a combobox dropdown as a date selector(calendar), I have set the column class as date and made it to accept different date formats, but couldn’t get calendar dropdown to work in a table.

Thanks,
Amit


Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/editable-combo-box

URLs in this post:

[1] findjobj: http://undocumentedmatlab.com/blog/findjobj-find-underlying-java-object/

[2] articles: http://undocumentedmatlab.com/blog/customizing-editboxes/

[3] JComboBox: http://docs.oracle.com/javase/7/docs/api/javax/swing/JComboBox.html

[4] here: http://undocumentedmatlab.com/blog/additional-uicontrol-tooltip-hacks/#truncated_text

[5] javacomponent: http://undocumentedmatlab.com/blog/javacomponent/

[6] here: http://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html

[7] has always been: http://undocumentedmatlab.com/blog/xlsread-functionality-change-in-r2012a/

[8] here: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&currency_code=USD&business=altmany@gmail.com&amount=29&item_name=Matlab+uicontrols+customization+report

[9] Matlab-Java programming book: http://undocumentedmatlab.com/matlab-java-book/

[10] Using JIDE combo-boxes : https://undocumentedmatlab.com/articles/using-jide-combo-boxes

[11] Common javacomponent problems : https://undocumentedmatlab.com/articles/common-javacomponent-problems

[12] Additional uicontrol tooltip hacks : https://undocumentedmatlab.com/articles/additional-uicontrol-tooltip-hacks

[13] Auto-completion widget : https://undocumentedmatlab.com/articles/auto-completion-widget

[14] The javacomponent function : https://undocumentedmatlab.com/articles/javacomponent

[15] GUI integrated HTML panel : https://undocumentedmatlab.com/articles/gui-integrated-html-panel

[16] : https://undocumentedmatlab.com/blog/editable-combo-box#comment-330718

[17] : http://www.mathworks.com/help/matlab/ref/uicontrol.html

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.