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

Listbox layout customization

Posted By Yair Altman On November 13, 2013 | 14 Comments

I haven’t written on listboxes in a long while, and since I’ve recently posted on related controls (editbox [1], combo-box [2]), I thought of following up with an article on customizing Matlab listbox layout. By the end of today’s article, you should be able to customize the layout of items within your listbox, such as the following:

Customized listbox layout   Customized listbox layout
Customized listbox layouts


For the following hacks, we need to gain access to the listbox control’s underlying Java component, which is a MathWorks class that extends the standard JList [3]. We can get this component’s reference using the findjobj utility [4]:

>> hListbox = uicontrol('Style','List', 'String',{'item #1','item #2'});
>> jScrollPane = java(findjobj(hListbox))
jScrollPane =
com.mathworks.hg.peer.utils.UIScrollPane[...]
>> jListbox = jScrollPane.getViewport.getView
jListbox =
com.mathworks.hg.peer.ListboxPeer$UicontrolList[...]

Like multi-line editboxes, listboxes are actually composed of a container (a com.mathworks.hg.peer.utils.UIScrollPane object) that includes three children, as expected from any JScrollPane [5]: a javax.swing.JViewport that contains the ListboxPeer$UicontrolList component, and horizontal/vertical scrollbars. I explained how to customize the scrollbars [6] in an article back in early 2010.
Today we are not interested in the scroll-pane or scollbars, but rather the jListbox component that takes up the view-port’s contents. This component includes many useful properties that we can access and modify, including several that control the layout of the list items:
LayoutOrientation sets the layout of listbox items within the viewport. Possible values include:

  • The default value (jListbox.VERTICAL=0) indicates the regular top-to-bottom arrangement
  • jListbox.VERTICAL_WRAP=1 sets a horizontal item layout, wrapping to a new row as necessary for the maximum number of rows determined by the VisibleRowCount property (default=8)
  • jListbox.HORIZONTAL_WRAP=2 sets a vertical item layout, wrapping to a new column at row number VisibleRowCount

For example:

jListbox.setLayoutOrientation(jListbox.HORIZONTAL_WRAP);
jListbox.setVisibleRowCount(3);
set(jListbox, 'LayoutOrientation',2, 'VisibleRowCount',3);  % equivalent alternative

LayoutOrientation = VERTICAL = 0
VisibleRowCount is irrelevant

LayoutOrientation = VERTICAL_WRAP = 1
VisibleRowCount = 3

LayoutOrientation = HORIZONTAL_WRAP = 2
VisibleRowCount = 3

FixedCellHeight and FixedCellWidth hold the listbox’s cells height (default=13 pixels) and width (default=-1). A value of -1 means that the actual size is determined by the default platform-dependent CellRenderer size:


FixedCellHeight = -1
FixedCellWidth = -1

FixedCellHeight = 10
FixedCellWidth = 30

FixedCellHeight = 16
FixedCellWidth = 50

We can use these properties to display a selection matrix of icons. For example, let’s display the icons in Matlab standard icons folder:

% Prepare the list of ImageIcon objects
iconsFolder = fullfile(matlabroot,'toolbox/matlab/icons');
imgs = dir(fullfile(iconsFolder,'*.gif'));
for iconIdx = 1 : length(imgs)
   iconFilename = fullfile(iconsFolder,imgs(iconIdx).name);
   iconFilename = strrep(iconFilename, '\', '/');
   htmlStr{iconIdx} = [''];  % no need for 
end
% Display in a standard one-column listbox
hListbox = uicontrol('style','list', 'string',htmlStr, 'position',[10,10,160,90]);
% Modify the listbox layout to display 18x18-pixel cells
jScrollPane = findjobj(hListbox);
jListbox = jScrollPane.getViewport.getView;
jListbox.setLayoutOrientation(jListbox.HORIZONTAL_WRAP)
jListbox.setVisibleRowCount(4)
jListbox.setFixedCellWidth(18)   % icon width=16  + 2px margin
jListbox.setFixedCellHeight(18)  % icon height=16 + 2px margin
jListbox.repaint  % refresh the display

Customized listbox layout
Customized listbox layout

Other interesting things that we can do with listboxes (among others):

Note that while the code above used the underlying Java component, absolutely no knowledge of Java is required to understand it or use it. In fact, the entire code above is pure Matlab, simply setting the component’s properties and calling its methods, and using its inherent support of HTML strings.
Much more advanced customizations are possible at the Java level, especially using a dedicated CellRenderer. 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 [9] ($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 [10].
If you’d like me to personally add similar magic to your GUI, email me [11] to see if I can help.

Advanced listbox CellRenderer customization
Advanced listbox CellRenderer customization

Now tell the truth – doesn’t Matlab’s standard listbox look kinda boring after all this? 🙂

Categories: GUI, Java, Medium risk of breaking in future versions, UI controls


14 Comments (Open | Close)

14 Comments To "Listbox layout customization"

#1 Comment By Robert Cumming On November 14, 2013 @ 10:56

Yair,

Excellent stuff

I don’t know if you’ve seen the [18] which I created which uses some of the items I learn’t on your site about formating and customising listboxes?

The utility uses pure matlab code with an API to make multi column (formatable) listboxes.

Regards

#2 Comment By Yair Altman On November 14, 2013 @ 16:00

@Robert – I haven’t seen it until now, but it looks impressive…
[18]

#3 Comment By michael On March 22, 2014 @ 09:44

Hi Yair,

thanks for this powerful tips and tricks, so far i was not a big fan of Matlab mainly because of very limited GUI functions, but now i start to believe in it.
I ordered your book, meanwhile i have a few questions if you don’t mind me to ask:
– is that possible to have a listbox with Popup menu and submenu to give options on Font/ color…
– i can not find how to change list row color with Javax.
rgds,
Michael

#4 Comment By Yair Altman On March 22, 2014 @ 10:02

@Michael –

1) you can set the UIContextMenu property of the listbox with whatever functionality that you wish – see the [19].

2) you can use HTML formatting for this – see [20].

#5 Comment By Michael On March 22, 2014 @ 15:29

Hi Yair,
I’m already using javax to customize the ListBox and other uicontrol …..is there any way to add popup menu and submenu with javax ? same for change listbox row color.

rgds,
Michael

#6 Comment By Yair Altman On March 22, 2014 @ 15:37

Of course you can do all that in Java (I don’t know why you call it javax), it’s called a JPopupMenu. But this is a Matlab blog, not a Java blog. So if you insist in using Java for this then I suggest that you check one of the numerous Java resources, either online or offline (books). You can start [21].

#7 Comment By Sebastian On February 26, 2019 @ 14:32

I have an issue here. I also use a Listbox with HTML code in it, and my figure resizes the listbox whenever the figure size is changed. Now it seems that the value set with ‘setFixedCellHeight’ is reset after resizing. Do you have an idea why?

And something else: On a colleagues PC the HTML text is cut-off at the bottom. Now I found out that he is using a larger Windows font size. Do you have an idea how to detect the needed list item height depending on the used default font?

Best regards,
Sebastian

#8 Comment By Yair Altman On February 26, 2019 @ 14:53

The component is reset/repainted by Matlab when it determines that a component resize is required. You can trap this in the containing panel’s SizeChangedFcn or possibly the Java component’s ComponentResizedCallback callbacks, where you can reapply all the customizations.

Regarding the font size, you can use the Java FontMetrics class to get the necessary information ( [22])

#9 Comment By Sebastian On February 28, 2019 @ 16:31

Oh all right. I thought I did something wrong and the settings should be consistent after repaints.

Also the FontMetrics class works like a charm. Thanks a lot for your quick help!

#10 Comment By Alex On August 11, 2019 @ 10:39

Hi Yair,
I am having a similar issue with Sebastian, for my GUI, I need to add/remove elements to the listbox interactively, causing the cell height to be reverted. I believe this is because MATLAB doesn’t have an addElement method for UIControls, meaning that the listbox needs to be redrawn everytime listbox.String is updated, resetting to the default MATLAB values for cell height and width. I can call ‘setFixedCellHeight’ for every callback that changes the listbox, but this causes flickering and you can see the cells change size everytime it is updated, do you have any suggestions for avoiding this issue?

Thanks

#11 Comment By Alex On August 11, 2019 @ 10:49

Hi Yair,
I am having a similar issue to Sebastian, where cell height is reset when listbox.String is updated. I believe MATLAB redraws the listbox whenever the String field is updated, as it doesn’t provide a ‘addElement’ method. I can manually use ‘setFixedCellHeight’ in callbacks following an update of the elements of the listbox, but the resize down to default and the resize back to the fixed height is clearly visible as a flicker, I am wondering if you have any suggestions in fixing this problem?

I tried using the addElement method of the DefaultListModel used in the listbox, but the ListModel is tied to updates in listbox.String field, rather than the other way around.

Many thanks,
Alex

#12 Comment By Yair Altman On August 11, 2019 @ 11:50

There is no simple solution. I think that if you call setFixedCellHeight immediately after updating the String property, without an intervening drawnow or repaint, then there should be no flicker. The flicker indicates that one or both of drawnow or repaint are being called between these two actions.

#13 Comment By Alex On August 13, 2019 @ 02:59

Hi Yair,
Thanks for your response. Annoyingly, and somewhat interestingly, a String update immediately followed by a setFixedCellHeight means that the listbox does NOT update its height at all, if you call getFixedCellHeight the value is still the default MATLAB value. I am not sure why this is.
One way to I found reduce to the flicker is adding a pause(0.01) before setFixedCellHeight call, which does allow the cell height to be set, but it isn’t much of a solution.

#14 Comment By Yair Altman On August 15, 2019 @ 23:54

Alex – the reason is probably that when updating the String property, the Matlab engine places a call to setFixedCellHeight (or some other method that eventually sets the cell height) on the Event Dispatch (EDT queue), and this gets executed in a separate thread asynchronously, a few millisecs later. So if you directly call setFixedCellHeight after setting String, your call is being overridden by the EDT call a few millisecs later and only then the listbox gets repainted, so in the end you see no visible change.
When you add a pause(0.01) before setFixedCellHeight, the EDT call gets executed before your direct call, and so this does produce the requested effect, but due to the intervening listbox repaint you will necessarily see a flicker.


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

URL to article: https://undocumentedmatlab.com/articles/listbox-layout-customization

URLs in this post:

[1] editbox: http://undocumentedmatlab.com/blog/editbox-data-input-validation/

[2] combo-box: http://undocumentedmatlab.com/blog/editable-combo-box/

[3] JList: http://docs.oracle.com/javase/tutorial/uiswing/components/list.html

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

[5] JScrollPane: http://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html

[6] customize the scrollbars: http://undocumentedmatlab.com/blog/customizing-listbox-editbox-scrollbars/

[7] Display HTML-formatted list items: http://undocumentedmatlab.com/blog/html-support-in-matlab-uicomponents/

[8] Setting dynamic tooltips and right-click context-menus: http://undocumentedmatlab.com/blog/setting-listbox-mouse-actions/

[9] 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

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

[11] email me: http://undocumentedmatlab.com/consulting/

[12] Setting listbox mouse actions : https://undocumentedmatlab.com/articles/setting-listbox-mouse-actions

[13] Customizing listbox & editbox scrollbars : https://undocumentedmatlab.com/articles/customizing-listbox-editbox-scrollbars

[14] Customizing listbox/combobox items : https://undocumentedmatlab.com/articles/customizing-listbox-combobox-items

[15] Listbox selection hacks : https://undocumentedmatlab.com/articles/listbox-selection-hacks

[16] Smart listbox & editbox scrollbars : https://undocumentedmatlab.com/articles/smart-listbox-editbox-scrollbars

[17] Button customization : https://undocumentedmatlab.com/articles/button-customization

[18] : http://www.mathworks.co.uk/matlabcentral/fileexchange/42670-multi-column-listbox

[19] : http://www.mathworks.com/help/matlab/ref/uicontextmenu.html

[20] : https://undocumentedmatlab.com/blog/html-support-in-matlab-uicomponents/

[21] : http://docs.oracle.com/javase/tutorial/uiswing/components/menu.html

[22] : https://docs.oracle.com/javase/tutorial/2d/text/measuringtext.html

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