UI controls – Undocumented Matlab https://undocumentedmatlab.com Charting Matlab's unsupported hidden underbelly Fri, 20 Oct 2017 09:57:44 +0000 en-US hourly 1 https://wordpress.org/?v=4.4.1 GUI formatting using HTMLhttps://undocumentedmatlab.com/blog/gui-formatting-using-html https://undocumentedmatlab.com/blog/gui-formatting-using-html#comments Wed, 05 Apr 2017 20:26:44 +0000 http://undocumentedmatlab.com/?p=6877
 
Related posts:
  1. Icon images & text in Matlab uicontrols HTML can be used to add image icons to Matlab listbox and popup (drop-down) controls. ...
  2. Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
  3. Multi-line uitable column headers Matlab uitables can present long column headers in multiple lines, for improved readability. ...
  4. Rich-contents log panel Matlab listboxes and editboxes can be used to display rich-contents HTML-formatted strings, which is ideal for log panels. ...
 
]]>
As I’ve mentioned several times in the past, HTML can be used for simple formatting of GUI controls, including font colors/sizes/faces/angles. With a bit of thought, HTML (and some CSS) can also be used for non-trivial formatting, that would otherwise require the use of Java, such as text alignment, background color, and using a combination of text and icons in the GUI control’s contents.

Alignment

For example, a question that I am often asked (latest example) is whether it is possible to left/center/right align the label within a Matlab button, listbox or table. While Matlab does not (yet) have properties that control alignment in uicontrols, we can indeed use HTML for this. There’s a catch though: if we simply tried to use <div align="left">…, it will not work. No error will be generated but we will not see any visible left-alignment. The reason is that internally, the text is contained within a snugly-fitting box. Aligning anything within a tight-fitting box obviously has no effect.

To solve the problem, we need to tell Matlab (or rather, the HTML interpreter used by the underlying Java control) to widen this internal box. One way to do this is to specify the width of the div tag, which can be enormous in order to span the entire available apace (<div width="999px" align="left">…). Another method is to simulate a simple HTML table that contains a single cell that holds the text, and then tell HTML the table cell’s width:

hButton.String   = '<html><tr><td width=9999 align=left>Left-aligned';  % left-align within a button
hTable.Data{2,1} = '<html><tr><td width=9999 align=right>And right';   % right-align within a specific uitable cell

centered (default) button label   right-aligned button label

Centered (default) and right-aligned button labels

Non-default alignment of uitable cells

Non-default alignment of uitable cells

I discussed the specific aspect of uicontrol content alignment in another post last year.

Background color

The same problem (and solution) applies to background colors: if we don’t enlarge the snugly-fitting internal bounding-box, any HTML bgcolor that we specify would only be shown under the text (i.e., within the internal box’s confines). In order to display bgcolor across the entire control/cell width, we need to enlarge the internal box’s width (the align and bgcolor tags can of course be used together):

hButton.String   = '<html><tr><td width=9999 bgcolor=#ffff00>Yellow';  % bgcolor within a button
hTable.Data{2,1} = '<html><tr><td width=9999 bgcolor=#ffff00>Yellow';  % bgcolor within a specific uitable cell

CSS

We can also use simple CSS, which provides more formatting customizability than plain HTML:

hTable.Data{2,1} = '<html><tr><td width=9999 style="background-color:yellow">Yellow';

HTML/CSS formatting is a poor-man’s hack. It is very crude compared to the numerous customization options available via Java. However, it does provide a reasonable solution for many use-cases, without requiring any Java. I discussed the two approaches for uitable cell formatting in this post.

[Non-]support in uifigures

Important note: HTML formatting is NOT [yet] supported by the new web-based uifigures. While uifigures can indeed be hacked with HTML/CSS content (details), this is not an easy task. Since it should be trivially easy for MathWorks to enable HTML content in the new web-based uifigures, I implore anyone who uses HTML in their Matlab GUI to let MathWorks know about it so that they could prioritize this R&D effort into an upcoming Matlab release. You can send an email to George.Caia at mathworks.com, who apparently handles such aspects in MathWorks’ R&D efforts to transition from Java-based GUIs to web-based ones. In my previous post I spotlit MathWorks user-feedback surveys about users’ use of Java GUI aspects, aimed in order to migrate as many of the use-cases as possible onto the new web-based framework. HTML/CSS support is a natural by-product of the fact that Matlab’s non-web-based GUI is based on Java Swing components (that inherently support HTML/CSS). But unfortunately the MathWorks surveys are specific to the javacomponent function and the figure’s JavaFrame property. In other words, many users might be using undocumented Java aspects by simply using HTML content in their GUI, without ever realizing it or using javacomponent. So I think that in this case a simple email to George.Caia at mathworks.com to let him know how you’re using HTML would be more useful. Maybe one day MathWorks will be kind enough to post a similar survey specific to HTML support, or maybe one day they’s just add the missing HTML support, if only to be done with my endless nagging. :-)

p.s. – I am well aware that we can align and bgcolor buttons in AppDesigner. But we can’t do this with individual table/listbox cells, and in general we can’t use HTML within uifigures without extensive hacks. I merely used the simple examples of button and uitable cell formatting in today’s post to illustrate the issue. So please don’t get hung up on the specifics, but rather on the broader issue of HTML support in uifigures.

And in the meantime, for as long as non-web-based GUI is still supported in Matlab, keep on enjoying the benefits that HTML/CSS provides.

Automated bug-fix emails

In an unrelated matter, I wish to express my Kudos to the nameless MathWorkers behind the scenes who, bit by bit, improve Matlab and the user experience: Over the years I’ve posted a few times my frustrations with the opaqueness of MathWorks’ bug-reporting mechanism. One of my complaints was that users who file bugs are not notified when a fix or workaround becomes available. That at least seems to have been fixed now. I just received a seemingly-automated email notifying me that one of the bugs that I reported a few years ago has been fixed. This is certainly a good step in the right direction, so thank you!

Happy Passover/Easter to all!

]]>
https://undocumentedmatlab.com/blog/gui-formatting-using-html/feed 1
Icon images & text in Matlab uicontrolshttps://undocumentedmatlab.com/blog/icon-images-in-matlab-uicontrols https://undocumentedmatlab.com/blog/icon-images-in-matlab-uicontrols#comments Wed, 28 Sep 2016 10:28:04 +0000 http://undocumentedmatlab.com/?p=6687
 
Related posts:
  1. Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
  2. Rich-contents log panel Matlab listboxes and editboxes can be used to display rich-contents HTML-formatted strings, which is ideal for log panels. ...
  3. Aligning uicontrol contents Matlab uicontrols can often be customized using plain HTML/CSS, without need for advanced Java. ...
  4. GUI integrated browser control A fully-capable browser component is included in Matlab and can easily be incorporated in regular Matlab GUI applications. This article shows how....
 
]]>
One of my consulting clients recently asked me if I knew any builtin Matlab GUI control that could display a list of colormap names alongside their respective image icons, in a listbox or popup menu (drop-down/combo-box):

Matlab listbox with icon images   Matlab popup menu (dropdown/combobox) with icon images

Matlab listbox (left) & popup menu (right) with icon images

My initial thought was that this should surely be possible, since Colormap is a documented figure property, that should therefore be listed inside the inspector window, and should therefore have an associated builtin Java control for the dropdown (just like other inspector controls, which are part of the com.mathworks.mlwidgets package, or possibly as a standalone control in the com.mathworks.mwswing package). To my surprise it turns out that for some unknown reason MathWorks neglected to add the Colormap property (and associated Java controls) to the inspector. This property is fully documented and all, just like Color and other standard figure properties, but unlike them Colormap can only be modified programmatically, not via the inspector window. Matlab does provide the related colormapeditor function and associated dialog window, but I would have expected a simple drop-down of the standard builtin colormaps to be available in the inspector. Anyway, this turned out to be a dead-end.

It turns out that we can relatively easily implement the requested listbox/combo-box using a bit of HTML magic, as I explained last week. The basic idea is for each of the listbox/combobox items to be an HTML string that contains both an <img> tag for the icon and the item label text. For example, such a string might contain something like this (parula is Matlab’s default colormap in HG2, starting in R2014b):

<html><img src="http://www.mathworks.com/help/matlab/ref/colormap_parula.png">parula

parula colormap image

parula colormap image

Of course, it would be a bit inefficient for each of the icons to be fetched from the internet. Luckily, the full set of Matlab documentation is typically installed on the local computer as part of the standard Matlab installation, beneath the docroot folder (e.g., C:\Program Files\Matlab\R2016b\help). In our specific case, the parula colormap image is located in:

imageFilename = [docroot, '/matlab/ref/colormap_parula.png']

Note that for a local image to be accepted by HTML, it needs to follow certain conventions. In our case, the HTML string for displaying the above image is:

<html><img src="file:///C:/Program%20Files/Matlab/R2016b/help/matlab/ref/colormap_parula.png">parula

Warning: it’s easy when dealing with HTML images in Matlab to get the format confused, resulting in a red-x icon. I discussed this issue some 4 years ago, which is still relevant.

How can we get the list of available builtin colormaps? The standard Matlab way of doing this would be something like this:

>> possibleColormaps = set(gcf,'Colormap')
possibleColormaps = 
     {}

but as we can see, for some unknown reason (probably another MathWorks omission), Matlab does not list the names of its available builtin colormaps.

Fortunately, all the builtin colormaps have image filenames that follow the same convention, which make it easy to get this list by simply listing the names of the relevant files, from which we can easily create the necessary HTML strings:

>> iconFiles = dir([docroot, '/matlab/ref/colormap_*.png']);
 
>> colormapNames = regexprep({iconFiles.name}, '.*_(.*).png', '$1')
colormapNames =  
  Columns 1 through 9
    'autumn'    'bone'    'colorcube'    'cool'    'copper'    'flag'    'gray'    'hot'    'hsv'
  Columns 10 through 18
    'jet'    'lines'    'parula'    'pink'    'prism'    'spring'    'summer'    'white'    'winter'
 
>> htmlStrings = strcat('<html><img width=200 height=10 src="file:///C:/Program%20Files/Matlab/R2016a/help/matlab/ref/colormap_', colormapNames', '.png">', colormapNames')
str = 
    '<html><img width=200 height=10 src="file:///C:/Program%20Files/Matlab/R2016a/help/matlab/ref/colormap_autumn.png">autumn'
    '<html><img width=200 height=10 src="file:///C:/Program%20Files/Matlab/R2016a/help/matlab/ref/colormap_bone.png">bone'
    '<html><img width=200 height=10 src="file:///C:/Program%20Files/Matlab/R2016a/help/matlab/ref/colormap_colorcube.png">colorcube'
    ...
 
>> hListbox = uicontrol(gcf, 'Style','listbox', 'Units','pixel', 'Pos',[10,10,270,200], 'String',htmlStrings);
>> hPopup   = uicontrol(gcf, 'Style','popup',   'Units','pixel', 'Pos',[10,500,270,20], 'String',htmlStrings);

…which results in the screenshots at the top of this post.

Note how I scaled the images to 10px high (so that the labels would be shown and not cropped vertically) and 200px wide (so that it becomes narrower than the default 434px). There’s really no need in this case for the full 434×27 image size – such flat images scale very nicely, even when their aspect ratio is not preserved. You can adjust the height and width values for a best fit with you GUI.

Unfortunately, it seems that HTML strings are not supported in the new web-based uifigure controls. This is not really Matlab’s fault because the way to customize labels in HTML controls is via CSS: directly embedding HTML code in labels does not work (it’s a Java-Swing feature, not a browser feature). I really hope that either HTML or CSS processing will be enabled for web-based uicontrol in a future Matlab release, because until that time uifigure uicontrols will remain seriously deficient compared to standard figure uicontrols. Until then, if we must use uifigures and wish to customize our labels or listbox items, we can directly access the underlying web controls, as Iliya explained here.


A blog reader recently complained that I’m abusing Swing and basically making Matlab work in unnatural ways, “something it was never meant to be“. I feel that using HTML as I’ve shown last week and in this post would fall under the same category in his eyes. To him and to others who complain I say that I have absolutely no remorse about doing this. When I purchase anything I have the full rights (within the scope of the license) to adapt it in whatever way fits my needs. As a software developer and manager for over 25 years, I’ve developed in dozens of programming languages and environments, and I still enjoy [ab]using Matlab. Matlab is a great environment to get things done quickly and if this sometimes requires a bit of HTML or Java hacks that make some people cringe, then that’s their problem, not mine – I’m content with being able to do in Matlab [nearly] everything I want, quickly, and move on to the next project. As long as it gets the job done, that’s fine by me. If this makes me more of an engineer than a computer scientist, then so be it.

On the flip side, I say to those who claim that Matlab is lacking in this or that aspect, that in most likelihood the limitation is only in their minds, not in Matlab – we can do amazing stuff with Matlab if we just open our minds, and possibly use some undocumented hacks. I’m not saying that Matlab has no limitations, I’m just saying that in most cases they can be overcome if we took the time and trouble to look for a solution. Matlab is a great tool and yet many people are not aware of its potential. Blaming Matlab for its failings is just an easy excuse in many cases. Of course, MathWorks could help my crusade on this subject by enabling useful features such as easy GUI component customizations…

On this sad day, I wish you all Shanah Tova!

]]>
https://undocumentedmatlab.com/blog/icon-images-in-matlab-uicontrols/feed 5
Aligning uicontrol contentshttps://undocumentedmatlab.com/blog/aligning-uicontrol-contents https://undocumentedmatlab.com/blog/aligning-uicontrol-contents#comments Thu, 22 Sep 2016 13:10:18 +0000 http://undocumentedmatlab.com/?p=6663
 
Related posts:
  1. Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
  2. Rich-contents log panel Matlab listboxes and editboxes can be used to display rich-contents HTML-formatted strings, which is ideal for log panels. ...
  3. Multi-line uitable column headers Matlab uitables can present long column headers in multiple lines, for improved readability. ...
  4. Undocumented button highlighting Matlab button uicontrols can easily be highlighted by simply setting their Value property. ...
 
]]>
Matlab automatically aligns the text contents of uicontrols: button labels are centered, listbox contents are left-aligned, and table cells align depending on their contents (left-aligned for strings, centered for logical values, and right-aligned for numbers). Unfortunately, the control’s HorizontalAlignment property is generally ignored by uicontrols. So how can we force Matlab buttons (for example) to have right-aligned labels, or for listbox/table cells to be centered? Undocumented Matlab has the answer, yet again…

It turns out that there are at least two distinct ways to set uicontrol alignment, using HTML and using Java. Today I will only discuss the HTML variant.

The HTML method relies on the fact that Matlab uicontrols accept and process HTML strings. This was true ever since Matlab GUI started relying on Java Swing components (which inherently accept HTML labels) over a decade ago. This is expected to remain true even in Matlab’s upcoming web-based GUI system, since Matlab would need to consciously disable HTML in its web components, and I see no reason for MathWorks to do so. In short, HTML parsing of GUI control strings is here to stay for the foreseeable future.

% note: no need to close HTML tags, e.g. </font></html>
uicontrol('Style','list', 'Position',[10,10,70,70], 'String', ...
          {'<HTML><FONT color="red">Hello</Font></html>', 'world', ...
           '<html><font style="font-family:impact;color:green"><i>What a', ...
           '<Html><FONT color="blue" face="Comic Sans MS">nice day!'});

Listbox with HTML items

Listbox with HTML items

While HTML formatting is generally frowned-upon compared to the alternatives, it provides a very quick and easy way to format text labels in various different manners, including using a combination of font faces, sizes, colors and other aspects (bold, italic, super/sub-script, underline etc.) within a single text label. This is naturally impossible to do with Matlab’s standard properties, but is super-easy with HTML placed in the label’s String property.

Unfortunately, while Java Swing (and therefore Matlab) honors only a [large] sub-set of HTML and CSS. The most important directives are parsed but some others are not, and this is often difficult to debug. Luckily, using HTML and CSS there are often multiple ways to achieve the same visual effect, so if one method fails we can usually find an alternative. Such was the case when a reader asked me why the following seemingly-simple HTML snippet failed to right-align his button label:

hButton.String = '<html><div style="text-align:right">text';

As I explained in my answer, it’s not Matlab that ignores the CSS align directive but rather the underlying Swing behavior, which snugly fits the text in the center of the button, and of course aligning text within a tight-fitting box has no effect. The workaround that I suggested simply forces Swing to use a non-tightly-fitting boundary box, within which we can indeed align the text:

pxPos = getpixelposition(hButton);
hButton.String = ['<html><div width="' num2str(pxPos(3)-20) 'px" align="right">text'];  % button margins use 20px

centered (default) button label   right-aligned button label

Centered (default) and right-aligned button labels

This solution is very easy to set up and maintain, and requires no special knowledge other than a bit of HTML/CSS, which most programmers know in this day and age.

Of course, the solution relies on the actual button size. So, if the button is created with normalized units and changes its size when its parent container is resized, we’d need to set a callback function on the parent (e.g., SizeChangedFcn of a uipanel) to automatically adjust the button’s string based on its updated size. A better solution that would be independent of the button’s pixel-size and would work even when the button is resized needs to use Java.

A related solution for table cells uses a different HTML-based trick: this time, we embed an HTML table cell within the Matlab control’s cell, employing the fact that HTML table cells can easily be aligned. We just need to ensure that the HTML cell is defined to be larger than the actual cell width, so that the alignment fits well. We do this by setting the HTML cell width to 9999 pixels (note that the tr and td HTML tags are necessary, but the table tag is optional):

uitable('Units','norm','Pos',[0,0,0.3,0.3], 'Data', ...
        {'Left', ...
         '<html><tr><td align=center width=9999>Center', ...
         '<html><tr><td align=right  width=9999>Right'});

Non-default alignment of uitable cells

Non-default alignment of uitable cells

As noted above, a better solution might be to set the underlying Java component’s alignment properties (or in the case of the uitable, its underlying JTable component’s cellrenderer’s alignment). But in the general case, simple HTML such as above could well be sufficient.

]]>
https://undocumentedmatlab.com/blog/aligning-uicontrol-contents/feed 6
Listbox selection hackshttps://undocumentedmatlab.com/blog/listbox-selection-hacks https://undocumentedmatlab.com/blog/listbox-selection-hacks#comments Wed, 13 Jul 2016 15:36:19 +0000 http://undocumentedmatlab.com/?p=6534
 
Related posts:
  1. Editbox data input validation Undocumented features of Matlab editbox uicontrols enable immediate user-input data validation...
  2. Continuous slider callback Matlab slider uicontrols do not enable a continuous-motion callback by default. This article explains how this can be achieved using undocumented features....
  3. Matlab and the Event Dispatch Thread (EDT) The Java Swing Event Dispatch Thread (EDT) is very important for Matlab GUI timings. This article explains the potential pitfalls and their avoidance using undocumented Matlab functionality....
  4. Customizing combobox popups Matlab combobox (dropdown) popups can be customized in a variety of ways. ...
 
]]>
Last week a reader on the CSSM newsgroup asked whether it is possible to programmatically deselect all listbox items. By default, Matlab listboxes enable a single item selection: trying to deselect it interactively has no effect, while trying to set the listbox’s Value property to empty ([]) results in the listbox disappearing and a warning issued to the Matlab console:

Single-selection Matlab listbox

>> hListbox = uicontrol('Style','list', 'String',{'item #1','item #2','item #3','item #4','item #5','item #6'});
>> set(hListbox,'Value',[]);
Warning: Single-selection 'listbox' control requires a scalar Value.
Control will not be rendered until all of its parameter values are valid
(Type "warning off MATLAB:hg:uicontrol:ValueMustBeScalar" to suppress this warning.)

The reader’s question was whether there is a way to bypass this limitation so that no listbox item will be selected. The answer to this question was provided by MathWorker Steve(n) Lord. Steve is a very long-time benefactor of the Matlab community with endless, tireless, and patient advise to queries small and large (way beyond the point that would have frustrated mere mortals). Steve pointed out that by default, Matlab listboxes only enable a single selection – not more and not less. However, when the listbox’s Max value is set to be >1, the listbox enables multiple-items selection, meaning that Value accepts and reports an array of item indices, and there is nothing that prevents this array from being empty (meaning no items selected):

>> hListbox = uicontrol('Style','list', 'Max',2, 'String',{'item #1','item #2','item #3','item #4','item #5','item #6'});
>> set(hListbox,'Value',[]);  % this is ok - listbox appears with no items selected

Note: actually, the listbox checks the value of MaxMin, but by default Min=0 and there is really no reason to modify this default value, just Max.

While this makes sense if you think about it, the existing documentation makes no mention of this fact:

The Max property value helps determine whether the user can select multiple items in the list box simultaneously. If Max – Min > 1, then the user can select multiple items simultaneously. Otherwise, the user cannot select multiple items simultaneously. If you set the Max and Min properties to allow multiple selections, then the Value property value can be a vector of indices.

Some readers might think that this feature is not really undocumented, since it does not directly conflict with the documentation text, but then so are many other undocumented aspects and features on this blog, which are not mentioned anywhere in the official documentation. I contend that if this feature is officially supported, then it deserves an explicit sentence in the official documentation.

However, the original CSSM reader wanted to preserve Matlab’s single-selection model while enabling deselection of an item. Basically, the reader wanted a selection model that enables 0 or 1 selections, but not 2 or more. This requires some tweaking using the listbox’s selection callback:

set(hListbox,'Callback',@myCallbackFunc);
 
...
function test(hListbox, eventData)
   value = get(hListbox, 'Value');
   if numel(value) > 1
       set(hListbox, 'Value', value(1));
   end
end

…or a callback-function version that is a bit better because it takes the previous selection into account and tries to set the new selection to the latest-selected item (this works in most cases, but not with shift-clicks as explained below):

function myCallbackFunc(hListbox, eventData)
   lastValue = getappdata(hListbox, 'lastValue');
   value = get(hListbox, 'Value');
   if ~isequal(value, lastValue)
      value2 = setdiff(value, lastValue);
      if isempty(value2)
         setappdata(hListbox, 'lastValue', value);
      else
         value = value2(1);  % see quirk below
         setappdata(hListbox, 'lastValue', value);
         set(hListbox, 'Value', value);
      end
   end
end

This does the job of enabling only a single selection at the same time as allowing the user to interactively deselect that item (by ctrl-clicking it).

There’s just a few quirks: If the user selects a block of items (using shift-click), then only the second-from-top item in the block is selected, rather than the expected last-selected item. This is due to line #9 in the callback code which selects the first value. Matlab does not provide us with information about which item was clicked, so this cannot be helped using pure Matlab. Another quirk that cannot easily be solved using pure Matlab is the flicker that occurs when the selection changes and is then corrected by the callback.

We can solve both of these problems using the listbox’s underlying Java component, which we can retrieve using my findjobj utility:

% No need for the standard Matlab callback now
set(hListbox,'Callback',[]);
 
% Get the underlying Java component peer
jScrollPane = findjobj(h);
jListbox = jScrollPane.getViewport.getView;
jListbox = handle(jListbox,'CallbackProperties');  % enable callbacks
 
% Attach our callback to the listbox's Java peer
jListbox.ValueChangedCallback = {@myCallbackFunc, hListbox};
 
...
function myCallbackFunc(jListbox, eventData, hListbox)
   if numel(jListbox.getSelectedIndices) > 1
      set(hListbox, 'Value', jListbox.getLeadSelectionIndex+1);  % +1 because Java indices start at 0
   end
end

We can use a similar mechanism to control other aspects of selection, for example to enable only up to 3 selections but no more etc.

We can use this underlying Java component peer for a few other useful selection-related hacks: First, we can use the peer’s RightSelectionEnabled property or setRightSelectionEnabled() method to enable the user to select by right-clicking listbox items (this is disabled by default):

jListbox.setRightSelectionEnabled(true);  % false by default
set(jListbox,'RightSelectionEnabled',true);  % equivalent alternative

A similarly useful property is DragSelectionEnabled (or the corresponding setDragSelectionEnabled() method), which is true by default, and controls whether the selection is extended to other items when the mouse drags an item up or down the listbox.

Finally, we can control whether in multi-selection mode we enable the user to only select a single contiguous block of items, or not (which is Matlab’s default behavior). This is set via the SelectionMode property (or associated setSelectionMode() method), as follows:

jListbox.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
jListbox.setSelectionMode(1);  % equivalent alternative (less maintainable/readable, but simpler)

SINGLE_SELECTION (default for Max=1)SINGLE_INTERVAL_SELECTION (only possible with Java)MULTIPLE_INTERVAL_SELECTION (default for Max>1)
SINGLE_SELECTION =0SINGLE_INTERVAL_SELECTION =1MULTIPLE_INTERVAL_SELECTION =2
(Matlab default for Max=1)(only possible with Java)(Matlab default for Max>1)

Additional listbox customizations can be found in related posts on this blog (see links below), or in section 6.6 of my Matlab-Java Programming Secrets book (which is still selling nicely almost five years after its publication, to the pleasant surprise of my publisher…).

]]>
https://undocumentedmatlab.com/blog/listbox-selection-hacks/feed 4
Smart listbox & editbox scrollbarshttps://undocumentedmatlab.com/blog/smart-listbox-editbox-scrollbars https://undocumentedmatlab.com/blog/smart-listbox-editbox-scrollbars#comments Wed, 20 Apr 2016 17:47:46 +0000 http://undocumentedmatlab.com/?p=6379
 
Related posts:
  1. 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....
  2. Editbox data input validation Undocumented features of Matlab editbox uicontrols enable immediate user-input data validation...
  3. Customizing combobox popups Matlab combobox (dropdown) popups can be customized in a variety of ways. ...
  4. GUI integrated HTML panel Simple HTML can be presented in a Java component integrated in Matlab GUI, without requiring the heavy browser control....
 
]]>
A good friend recently asked me for examples where using Java in Matlab programs provides a significant benefit that would offset the risk of using undocumented/unsupported functionality, which may possibly stop working in some future Matlab release. Today I will discuss a very easy Java-based hack that in my opinion improves the appearance of Matlab GUIs with minimal risk of a catastrophic failure in a future release.

The problem with Matlab listbox and multi-line editbox controls in the current (non web-based) GUI, is that they use a scrollbar whose behavior policy is set to VERTICAL_SCROLLBAR_ALWAYS. This causes the vertical scrollbar to appear even when the listbox does not really require it. In many cases, when the listbox is too narrow, this also causes the automatic appearance of a horizontal scrollbar. The end result is a listbox that displays 2 useless scrollbars, that possibly hide some listbox contents, and are a sore to the eyes:

Standard (left) and smart (right) listbox scrollbars

Standard (left) and smart (right) listbox scrollbars

   
default scrollbars (VERTICAL_SCROLLBAR_ALWAYS)

default scrollbars (VERTICAL_SCROLLBAR_ALWAYS)

non-default scrollbars (VERTICAL_SCROLLBAR_AS_NEEDED)     non-default scrollbars (VERTICAL_SCROLLBAR_AS_NEEDED)

non-default scrollbars (VERTICAL_SCROLLBAR_AS_NEEDED)

By default, Matlab implements a vertical scrollbar policy of VERTICAL_SCROLLBAR_ALWAYS for sufficiently tall uicontrols (>20-25 pixels, which practically means always) and VERTICAL_SCROLLBAR_NEVER for shorter uicontrols (this may possibly be platform-dependent).

A similar problem happens with the horizontal scrollbar: Matlab implements a horizontal scrollbar policy of HORIZONTAL_SCROLLBAR_NEVER for all editboxes and also for narrow listboxes (<35 pixels), and HORIZONTAL_SCROLLBAR_AS_NEEDED for wide listboxes.

In many cases we may wish to modify the settings, as in the example shown above. The solution to this is very easy, as I explained back in 2010.

All we need to do is to retrieve the control’s underlying Java reference (a Java JScrollPane object) and change the policy value to VERTICAL_SCROLLBAR_AS_NEEDED:

% Create a multi-line (Max>1) editbox uicontrol
hEditbox = uicontrol('style','edit', 'max',5, ...);
 
try  % graceful-degradation for future compatibility
   % Get the Java scroll-pane container reference
   jScrollPane = findjobj(hEditbox);
 
   % Modify the scroll-pane's scrollbar policies
   % (note the equivalent alternative methods used below)
   set(jScrollPane,'VerticalScrollBarPolicy',javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);   %VERTICAL_SCROLLBAR_AS_NEEDED=20
   jScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);  %HORIZONTAL_SCROLLBAR_AS_NEEDED=30
catch
   % Never mind...
end

Note that updating the uicontrol handle Position property has the side-effect of automatically reverting the scrollbar policies to their default values (HORIZONTAL_SCROLLBAR_NEVER and VERTICAL_SCROLLBAR_ALWAYS/NEVER). This also happens whenever the uicontrol is resized interactively (by resizing its container figure window, for example). It is therefore advisable to set jScrollPane’s ComponentResizedCallback property to “unrevert” the policies:

cbFunc = @(h,e) set(h,'VerticalScrollBarPolicy',20, 'HorizontalScrollBarPolicy',30);
hjScrollPane = handle(jScrollPane,'CallbackProperties');
set(hjScrollPane,'ComponentResizedCallback',cbFunc);

smart_scrollbars utility

I created a new utility called smart_scrollbars that implements all of this, which you can download from the Matlab File Exchange. The usage in Matlab code is very simple:

% Fix scrollbars for a specific listbox
hListbox = uicontrol('style','list', ...);
smart_scrollbars(hListbox)
 
% Fix scrollbars for a specific editbox
hEditbox = uicontrol('style','edit', 'max',5, ...);
smart_scrollbars(hEditbox)
 
% Fix all listbox/editbox scrollbars in a panel or figure
smart_scrollbars              % fixes all scrollbars in current figure (gcf)
smart_scrollbars(hFig)        % fixes all scrollbars in a specific figure
smart_scrollbars(hContainer)  % fixes all scrollbars in a container (panel/tab/...)

Performance considerations

Finding the underlying JScrollPane reference of Matlab listboxes/editboxes can take some time. While the latest version of findjobj significantly improved the performance of this, it can still take quite a while in complex GUIs. For this reason, it is highly advisable to limit the search to a Java container of the control that includes as few internal components as possible.

In R2014b or newer, this is easily achieved by wrapping the listbox/editbox control in a tightly-fitting invisible uipanel. The reason is that in R2014b, uipanels have finally become full-fledged Java components (which they weren’t until then), but more to the point they now contain a property with a direct reference to the underlying JPanel. By using this panel reference we limit findjobj‘s search only to the contained scrollpane, and this is much faster:

% Slower code:
hListbox = uicontrol('style','list', 'parent',hParent, 'pos',...);
smart_scrollbars(hListbox)
 
% Much faster (using a tightly-fitting transparent uipanel wrapper):
hPanel = uipanel('BorderType','none', 'parent',hParent, 'pos',...);  % same position/units/parent as above
hListbox = uicontrol('style','list', 'parent',hPanel, 'units','norm', 'pos',[0,0,1,1], ...);
smart_scrollbars(hListbox)

The smart_scrollbars utility detects cases where there is a potential for such speedups and reports it in a console warning message:

>> smart_scrollbars(hListbox)
Warning: smart_scrollbars can be much faster if the list/edit control is wrapped in a tightly-fitting uipanel (details)

If you wish, you can suppress this warning using code such as the following:

oldWarn = warning('off', 'YMA:smart_scrollbars:uipanel');
smart_scrollbars(hListbox)
warning(oldWarn);  % restore warnings

Musings on future compatibility

Going back to my friend’s question at the top of today’s post, the risk of future compatibility was highlighted in the recent release of Matlab R2016a, which introduced web-based uifigures and controls, for which the vast majority of Java hacks that I presented in this blog since 2009 (including today’s hack) will not work. While the full transition from Java-based to web-based GUIs is not expected anytime soon, this recent addition highlighted the risk inherent in using unsupported functionality.

Users can take a case-by-case decision whether any improved functionality or appearance using Java hacks is worth the extra risk: On one hand, such hacks have been quite stable and worked remarkably well for the past decade, and will probably continue working into 2020 or so (or longer if you keep using a not up-to-the-moment Matlab release, or if you create compiled applications). On the other hand, once they stop working sometime in R2020a (or whenever), major code rewrites may possibly be required, depending on the amount of dependency of your code on these hacks.

There is an obvious tradeoff between improved GUIs now and for the coming years, versus increased maintainability cost a few years in the future. Each specific GUI will have its own sweet spot on the wide spectrum between using no such hacks at all, through non-critical hacks that provide graceful functionality degradation if they ever fail, to major Java-based functionality that would require complete rework. It is certainly NOT an all-or-nothing decision. Users who take the conservative approach of using no unsupported feature at all, lose the opportunity to have professional grade Matlab GUIs today and in the upcoming years. Decisions, decisions, …

In any case, we can reduce the risk of using such hacks today by carefully wrapping all their code in try-catch blocks. This way, even if the code fails in some future Matlab release, we’d still be left with a working implementation based on fully-supported functionality. This is the reason why I’ve used such a block in the code snippet above, as well as in my smart_scrollbars utility. What this means is that you can safely use smart_scrollbars in your code today and if the worst happens and it stops working in a few years, then it will simply do nothing without causing any error. In other word, future compatibility in the form of graceful degradation. I strongly advise using such defensive coding techniques whenever you use unsupported features.

]]>
https://undocumentedmatlab.com/blog/smart-listbox-editbox-scrollbars/feed 4
Faster findjobjhttps://undocumentedmatlab.com/blog/faster-findjobj https://undocumentedmatlab.com/blog/faster-findjobj#comments Mon, 11 Apr 2016 09:18:14 +0000 http://undocumentedmatlab.com/?p=6376
 
Related posts:
  1. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
  2. 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....
  3. Customizing Matlab labels Matlab's text uicontrol is not very customizable, and does not support HTML or Tex formatting. This article shows how to display HTML labels in Matlab and some undocumented customizations...
  4. Continuous slider callback Matlab slider uicontrols do not enable a continuous-motion callback by default. This article explains how this can be achieved using undocumented features....
 
]]>
My findjobj utility, created in 2007 and updated over the years, has received wide recognition and is employed by numerous Matlab programs, including a few dozen utilities in the Matlab File Exchange. I am quite proud of this utility and find it extremely useful for customizing Matlab controls in many ways that are impossible using standard Matlab properties. I have shown many examples of this in this blog over the past years.

I am happy to announce that I have just uploaded a new version of findjobj to the Matlab File Exchange, which significantly improves the utility’s performance for the most common use-case of a single input and a single output, namely finding the handle of the underlying Java component (peer) of a certain Matlab control:

>> hButton = uicontrol('String','click me!');
 
>> tic, jButton = findjobj(hButton); toc  % old findjobj
Elapsed time is 1.513217 seconds.
 
>> tic, jButton = findjobj(hButton); toc  % new findjobj
Elapsed time is 0.029348 seconds.

The new findjobj is backward-compatible with the old findjobj and with all prior Matlab releases. It is a drop-in replacement that will significantly improve your program’s speed.

The new version relies on several techniques:

First, as I showed last year, in HG2 (R2014 onward), Matlab uipanels have finally become full-featured Java JPanels, that can be accessed and customized in many interesting manners. More to the point here, we can now directly access the underlying JPanel component handle using the uipanel‘s hidden JavaFrame property (thanks to MathWorks for supplying this useful hook!). The new findjobj version detects this and immediately returns this handle if the user specified a uipanel input.

I still do not know of any direct way to retrieve the underlying Java component’s handle for Matlab uicontrols, this has been a major frustration of mine for quite a few years. So, we need to find the containing Java container in which we will recursively search for the control’s underlying Java handle. In the old version of finjobj, we retrieve the containing figure’s JFrame reference and from it the ContentPane handle, and use this handle as the Java container that is recursively searched. This is quite slow when the figure window is heavily-laden with multiple controls. In the new version, we try to use the specified Matlab uicontrol‘s direct parent, which is very often a uipanel. In this case, we can directly retrieve the panel’s JPanel reference as explained above. This results in a must smaller and faster search since we need to recursively search far fewer controls within the container, compared to the figure’s ContentPane.

In addition, I used a suggestion by blog reader Hannes for a faster recursive search that uses the control’s tooltip rather than its size, position and class. Finally, the search order is reversed to search backward from the last child component, since this is the component that will most often contain the requested control peer.

Feel free to download and use the new findjobj version. The code for the fast variant can be found in lines #190-205 and #3375-3415.

Enjoy!

p.s. – as I explained last week, today’s discussion, and in general anything that has to do with Java peers of GUI controls, only relates to the existing JFrame-based figure windows, not to the new web-based uifigure.

]]>
https://undocumentedmatlab.com/blog/faster-findjobj/feed 11
Adding dynamic properties to graphic handleshttps://undocumentedmatlab.com/blog/adding-dynamic-properties-to-graphic-handles https://undocumentedmatlab.com/blog/adding-dynamic-properties-to-graphic-handles#comments Wed, 16 Sep 2015 17:26:44 +0000 http://undocumentedmatlab.com/?p=6006
 
Related posts:
  1. New information on HG2 More information on Matlab's new HG2 object-oriented handle-graphics system...
  2. Performance: accessing handle properties Handle object property access (get/set) performance can be significantly improved using dot-notation. ...
  3. uiundo – Matlab’s undocumented undo/redo manager The built-in uiundo function provides easy yet undocumented access to Matlab's powerful undo/redo functionality. This article explains its usage....
  4. Matlab’s HG2 mechanism HG2 is presumably the next generation of Matlab graphics. This article tries to explore its features....
 
]]>
A client recently asked me to extend one of Matlab’s built-in graphic containers (uiflowcontainer in this specific case) with automatic scrollbars that would enable the container to act as a scroll-panel. The basic idea would be to dynamically monitor the container’s contents and when it is determined that they overflow the container’s boundaries, then attach horizontal/vertical scrollbars to enable scrolling the contents into view:

Scrollable Matlab container

Scrollable Matlab container

This may sound simple, but there are actually quite a few undocumented hacks that make this possible, including listening to ObjectChildAdded/ObjectChildRemoved events, location/size/visibility events, layout changes etc. Maybe I’ll blog about it in some future article.

Today’s post is focused on a specific aspect of this project, attaching dynamic properties to the builtin uiflowcontainer, that would enable users to modify the container’s properties directly, as well as control aspects of the scrolling using the new properties: handles to the parent container, as well as the horizontal and vertical scrollbars, and even a new refresh() method.

The “textbook” approach to this would naturally be to create a new class that extends (inherits) uiflowcontainer and includes these new properties and methods. Unfortunately, for some reason that escapes my understanding, MathWorks saw fit to make all of its end-use graphic object classes Sealed, such that they cannot be extended by users. I did ask for this to be changed long ago, but the powers that be apparently decided that it’s better this way.

So the fallback would be to create our own dedicated class having all the new properties as well as those of the original container, and ensure that all the property values are synchronized in both directions. This is probably achievable, if you have a spare few days and a masochistic state of mind. Being the lazy bum and authority-rebel that I am, I decided to take an alternate approach that would simply add my new properties to the built-in container handle. The secret lies in the undocumented function schema.prop (for HG1, R2014a and older) and the fully-documented addprop function (for HG2, R2014b and newer).

In the examples below I use a panel, but this mechanism works equally well on any Matlab HG object: axes, lines, uicontrols, figures, etc.

HG2 – addprop function

The addprop function is actually a public method of the dynamicprops class. Both the dynamicprops class as well as its addprop function are fully documented. What is NOT documented, as far as I could tell, is that all of Matlab’s builtin handle graphics objects indirectly inherit dynamicprops, via matlab.graphics.Graphics, which is a high-level superclass for all HG objects. The bottom line is that we can dynamically add run-time properties to any HG object, without affecting any other object. In other words, the new properties will only be added to the handles that we specifically request, and not to any others. This suits me just fine:

hProp = addprop(hPanel, 'hHorizontalScrollBar');
hPanel.hHorizontalScrollBar = hMyScrollbar;
hProp.SetAccess = 'private';  % make this property read-only

The new property hHorizontalScrollBar is now added to the hPanel handle, and can be accessed just like any other read-only property. For example:

>> get(hPanel, 'hHorizontalScrollBar')
ans = 
    JavaWrapper

>> hPanel.hHorizontalScrollBar
ans = 
    JavaWrapper

>> hPanel.hHorizontalScrollBar = 123
You cannot set the read-only property 'hHorizontalScrollBar' of UIFlowContainer.

Adding new methods is more tricky, since we do not have a corresponding addmethod function. The trick I used was to create a new property having the requested new method’s name, and set its read-only value to a handle of the requested function. For example:

hProp = addprop(hPanel, 'refresh');
hPanel.refresh = @myRefreshFunc;
hProp.SetAccess = 'private';  % make this property read-only

We can then invoke the new refresh “method” using the familiar dot-notation:

hPanel.refresh();

Note: if you ever need to modify the initial value in your code, you should revert the property’s SetAccess meta-property to 'public' before Matlab will enable you to modify the value:

try
    % This will raise an exception if the property already exists
    hProp = addprop(hPanel, propName);
catch
    % Property already exists - find it and set its access to public
    hProp = findprop(hPanel, propName);
    hProp.SetAccess = 'public';
end
hPanel.(propName) = newValue;

HG1 – schema.prop function

In HG1 (R2014a and earlier), we can use the undocumented schema.prop function to add a new property to any HG handle (which is a numeric value in HG1). Donn Shull wrote about schema.prop back in 2011, as part of his series of articles on UDD (Unified Data Dictionary, MCOS’s precursor). In fact, schema.prop is so useful that it has its own blog tag here and appears in no less than 15 separate articles (excluding today). With HG2’s debut 2 years ago, MathWorks tried very hard to rid the Matlab code corpus of all the legacy schema-based, replacing most major functionalities with MCOS-based HG2 code. But so far it has proven impossible to get rid of schema completely, and so schema code is still used extensively in Matlab to this day (R2015b). Search your Matlab path for “schema.prop” and see for yourself.

Anyway, the basic syntax is this:

hProp = schema.prop(hPanel, propName, 'mxArray');

The 'mxArray' specifies that the new property can accept any data type. We can limit the property to only accept certain types of data by specifying a less-generic data type, among those recognized by UDD (details).

Note that the meta-properties of the returned hProp are somewhat different from those of HG2’s hProp. Taking this into account, here is a unified function that adds/updates a new property (with optional initial value) to any HG1/HG2 object:

function addProp(hObject, propName, initialValue, isReadOnly)
    try
        hProp = addprop(hObject, propName);  % HG2
    catch
        try
            hProp = schema.prop(hObject, propName, 'mxArray');  % HG1
        catch
            hProp = findprop(hObject, propName);
        end
    end
    if nargin > 2
        try
            hProp.SetAccess = 'public';  % HG2
        catch
            hProp.AccessFlags.PublicSet = 'on';  % HG1
        end
        hObject.(propName) = initialValue;
    end
    if nargin > 3 && isReadOnly
        try
            % Set the property as read-only
            hProp.SetAccess = 'private';  % HG2
        catch
            hProp.AccessFlags.PublicSet = 'off';  % HG1
        end
    end
end
]]>
https://undocumentedmatlab.com/blog/adding-dynamic-properties-to-graphic-handles/feed 4
Customizing Matlab uipanelshttps://undocumentedmatlab.com/blog/customizing-matlab-uipanels https://undocumentedmatlab.com/blog/customizing-matlab-uipanels#comments Wed, 25 Feb 2015 21:24:50 +0000 http://undocumentedmatlab.com/?p=5595
 
Related posts:
  1. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  2. Detecting window focus events Matlab does not have any documented method to detect window focus events (gain/loss). This article describes an undocumented way to detect such events....
  3. The javacomponent function Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...
  4. Enable/disable entire figure window Disabling/enabling an entire figure window is impossible with pure Matlab, but is very simple using the underlying Java. This article explains how....
 
]]>
The major innovation in Matlab release R2014b was the introduction of the new handle-based graphics system (HG2). However, this release also included a few other improvements to graphics/GUI that should not be overlooked. The most notable is that uitabs are finally officially documented/supported, following a decade or being undocumented (well, undocumented in the official sense, since I took the time to document this functionality in this blog and in my Matlab-Java book).

A less-visible improvement occurred with uipanels: Panels are very important containers when designing GUIs. They enable a visual grouping of related controls and introduce order to an otherwise complex GUI. Unfortunately, until R2014b panels were drawn at the canvas level, and did not use a standard Java Swing controls like other uicontrols. This made it impossible to customize uipanels in a similar manner to other GUI uicontrols (example).

In R2014b, uipanels have finally become standard Java Swing controls, a com.mathworks.hg.peer.ui.UIPanelPeer$UIPanelJPanel component that extends Swing’s standard javax.swing.JPanel and Matlab’s ubiquitous com.mathworks.mwswing.MJPanel. This means that we can finally customize it in various ways that are not available in plain Matlab.

We start the discussion with a simple Matlab code snippet. It is deliberately simple, since I wish to demonstrate only the panel aspects:

figure('Menubar','none', 'Color','w');
hPanel = uipanel('Title','Panel title', 'Units','norm', 'Pos',[.1,.1,.6,.7]);
hButton = uicontrol('String','Click!', 'Parent',hPanel);

Standard Matlab uipanel

Standard Matlab uipanel

Notice the default ‘etchedin’ panel border, which I hate (note the broken edges at the corners). Luckily, Swing includes a wide range of alternative borders that we can use. I’ve already demonstrated customizing Matlab uicontrols with Java borders back in 2010 (has it really been that long? wow!). In R2014b we can finally do something similar to uipanels:

The first step is to get the uipanel‘s underlying Java component’s reference. We can do this using my findjobj utility, but in the specific case of uipanel we are lucky to have a direct shortcut by using the panel’s undocumented hidden property JavaFrame and its PrintableComponent property:

>> jPanel = hPanel.JavaFrame.getPrintableComponent
jPanel =
com.mathworks.hg.peer.ui.UIPanelPeer$UIPanelJPanel[,0,0,97x74,...]

Let’s now take a look at the jPanel‘s border:

>> jPanel.getBorder
ans =
com.mathworks.hg.peer.ui.borders.TitledBorder@25cd9b97
 
>> jPanel.getBorder.get
                Border: [1x1 com.mathworks.hg.peer.ui.borders.EtchedBorderWithThickness]
          BorderOpaque: 0
                 Class: [1x1 java.lang.Class]
                 Title: 'Panel title'
            TitleColor: [1x1 java.awt.Color]
             TitleFont: [1x1 java.awt.Font]
    TitleJustification: 1
         TitlePosition: 2

Ok, simple enough. Let’s replace the border’s EtchedBorderWithThickness with something more appealing. We start with a simple red LineBorder having rounded corners and 1px width:

jColor = java.awt.Color.red;  % or: java.awt.Color(1,0,0)
jNewBorder = javax.swing.border.LineBorder(jColor, 1, true);  % red, 1px, rounded=true
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

Rounded-corners LineBorder

Rounded-corners LineBorder

Or maybe a thicker non-rounded orange border:

jColor = java.awt.Color(1,0.5,0);
jNewBorder = javax.swing.border.LineBorder(jColor, 3, false);  % orange, 3px, rounded=false
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

Another LineBorder example

Another LineBorder example

Or maybe a MatteBorder with colored insets:

jColor = java.awt.Color(0,0.3,0.8);  % light-blue
jNewBorder = javax.swing.border.MatteBorder(2,5,8,11,jColor)  % top,left,bottom,right, color
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

MatteBorder with solid insets

MatteBorder with solid insets

MatteBorder can also use an icon (rather than a solid color) to fill the border insets. First, let’s load the icon. We can either load a file directly from disk, or use one of Matlab’s standard icons. Here are both of these alternatives:

% Alternative #1: load from disk file
icon = javax.swing.ImageIcon('C:\Yair\star.gif');
 
% Alternative #2: load a Matlab resource file
jarFile = fullfile(matlabroot,'/java/jar/mlwidgets.jar');
iconsFolder = '/com/mathworks/mlwidgets/graphics/resources/';
iconURI = ['jar:file:/' jarFile '!' iconsFolder 'favorite_hoverover.png'];  % 14x14 px
icon = javax.swing.ImageIcon(java.net.URL(iconURI));

We can now pass this icon reference to MatteBorder‘s constructor:

w = icon.getIconWidth;
h = icon.getIconHeight;
jNewBorder = javax.swing.border.MatteBorder(h,w,h,w,icon)  % top,left,bottom,right, icon
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

MatteBorder with icon insets

MatteBorder with icon insets

Additional useful Swing borders can be found in the list of classes implementing the Border interface, or via the BorderFactory class. For example, let’s create a dashed border having a 3-2 ratio between the line lengths and the spacing:

jColor = java.awt.Color.blue;  % or: java.awt.Color(0,0,1);
lineWidth = 1;
relativeLineLength = 3;
relativeSpacing = 2;
isRounded = false;
jNewBorder = javax.swing.BorderFactory.createDashedBorder(jColor,lineWidth,relativeLineLength,relativeSpacing,isRounded);
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

StrokeBorder (dashed)

StrokeBorder (dashed)

After seeing all these possibilities, I think you’ll agree with me that Matlab’s standard uipanel borders look pale in comparison.

Have you used any interesting borders in your Matlab GUI? Or have you customized your panels in some other nifty manner? If so, then please place a comment below.

]]>
https://undocumentedmatlab.com/blog/customizing-matlab-uipanels/feed 14
Unorthodox checkbox usagehttps://undocumentedmatlab.com/blog/unorthodox-checkbox-usage https://undocumentedmatlab.com/blog/unorthodox-checkbox-usage#comments Wed, 14 Jan 2015 21:41:18 +0000 http://undocumentedmatlab.com/?p=5457
 
Related posts:
  1. UISplitPane UISplitPane was recently chosen as Matlab Central's Pick of the Week. Here I detail its use of some undocumented Matlab features....
  2. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  3. The javacomponent function Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...
  4. JTattoo look-and-feel demo A demo GUI that shows the effects of using different look-and-feels, including the JTatoo library, is presented. ...
 
]]>
A few weeks ago, Robert Cumming explained how we can use a Matlab uicontrol’s CData property to provide an optical illusion of a transparent background. Today I will discuss another usage of this property, providing a simple checkbox control the unorthodox appearance of a split-pane divider.

The underlying problem description is easy: we wish to have the ability to split a Matlab uipanel into two or more sub-panels, separated by a draggable horizontal/vertical divider. Such split-panes are standard in any semi-decent GUI, but for some reason were never incorporated in official Matlab. This is a real pity, but not to worry as there are at least two alternatives we could use:

UISplitPane

UISplitPane is a utility that I wrote back in 2009 that uses a Java JSplitPane divider and associates it with plain Matlab panels on both sides. This solves the problem of embedding Matlab axes in Java panels, such as the ones provided by the standard Java JSplitPane. A detailed description of the technique can be found in my dedicated post on this utility.

Two levels of UISplitPane, with customized dividers

Two levels of UISplitPane, with customized dividers

[hDown,hUp,hDiv1] = uisplitpane(gcf, 'Orientation','ver', 'dividercolor',[0,1,0]);
[hLeft,hRight,hDiv2] = uisplitpane(hDown, 'dividercolor','r', 'dividerwidth',3);
t=0:.1:10; 
hax1=axes('Parent',hUp);    plot(t,sin(t));
hax2=axes('parent',hLeft);  plot(t,cos(t));
hax3=axes('parent',hRight); plot(t,tan(t));
hDiv1.DividerLocation = 0.75;    % one way to modify divider properties...
set(hDiv2,'DividerColor','red'); % ...and this is another way...

Making UISplitPane work in HG2 (R2014b onward) was quite a pain: numerous changes had to be made. For example, dynamic UDD properties can no longer be added to Matlab handles, only to Java ones. For Matlab handles, we now need to use the addprop function. For such properties, the UDD meta-property SetFunction is now called SetMethod (and similarly for Get) and only accepts function handles (not function handle cells as in UDD). Also, the UDD meta-property AccessFlags.PublicSet='off' needed to change to SetAccess='private'. Also, handle.listener no longer works; instead, we need to use the addlistener function. There are quite a few other similar tweaks, but UISplitPanenow hopefully works well on both old (HG1, R2014a and earlier) and new (HG2, R2014b+) Matlab releases. Let me know if you still see unhandled issues.

UIExtras flex-box

UIExtras (officially named “GUI Layout Toolbox”) is a toolbox of very useful GUI handling functions related to layout management. Written within MathWorks and originally posted in 2010, it has been under continuous maintenance ever since. While being called a “toolbox”, it is in fact freely-downloadable from the Matlab File Exchange.

The new HG2 introduced in R2014b did not just make code porting difficult for me – uiextras’ developers (MathWorkers Ben Tordoff and David Sampson) also encountered great difficulties in porting the code and making sure that it is backward compatible with HG1. In the end they gave up and we now have two distinct versions of the toolbox: the original version for HG1 (R2014a and earlier) and a new version for HG2 (R2014b+).

In my opinion, uiextras is one of the greatest examples of Matlab code on the File Exchange. It is well-written, well-documented and highly performant (although I would also have preferred it to be a bit more robust, it sometimes complains when used). Readers could benefit greatly by studying its techniques, and today’s subject topic is one such example. Specifically, the split-pane divider in uiextras (used by HBoxFlex and VBoxFlex) is simply a Matlab uicontrol having a custom CData property. This CData value is computed and set programmatically (at the bottom of uix.Divider) to display a flat color with some markings at the center (“hand-holds”, a visual cue for interactive dragging, which can be turned off if requested). Thus, for a vertical divider (for an HBoxFlex container) of height 100 pixels and width of 5 pixels, we would get a CData of 100x5x3 (x3 for RGB colors):

hHBox = uiextras.HBoxFlex('Spacing',6, 'BackgroundColor','b');  % Spacing=6 means divider width =6px, and CData width =5px
hLeft  = uicontrol('parent',hHBox, 'style','check', 'string','Left split pane');
hRight = uicontrol('parent',hHBox, 'style','radio', 'string','Right split pane');

UIExtras HBoxFlex with draggable split-pane divider

UIExtras HBoxFlex with draggable split-pane divider

The divider handle is a private property, so we cannot readily access it. However, as I have explained last year, we can use the builtin struct function:

oldWarn = warning('off','MATLAB:structOnObject');  % temporarily disable warning message on discouraged usage
hHBox_data = struct(hHBox);  % this includes hidden/private properties
warning(oldWarn);
hDividers = hHBox_data.Dividers;  % multiple dividers are possible in HBoxFlex/VBoxFlex
cdata = get(hDividers(1), 'CData');

A very nice trick here is that this divider uicontrol is not a pushbutton as we might have expected. Instead, it is a checkbox control. And while it does not look anything like a standard checkbox (due to the custom CData), checkboxes (and radio-buttons) have a very important advantage that caused them to be preferable over buttons: in buttons, there is always a small border showing at the control’s edges, but checkboxes do not have any 3D appearance, or in other words they do not have a border — their CData can span the entire extent of the control. Neat, right?

This enables us to customize the appearance of checkboxes (and radios) to any arbitrary shape, by setting the relevant CData pixels to transparent/bgcolor (as Robert showed last week for buttons). Matlab GUI controls no longer need to look a boring rectangle. We can have clickable stars, draggable icons, and other similar uses. This really opens up the possibilities for rich GUI appearance. If anyone uses this feature, please do post a comment below (preferably with a nice screenshot!).

]]>
https://undocumentedmatlab.com/blog/unorthodox-checkbox-usage/feed 1
Customizing combobox popupshttps://undocumentedmatlab.com/blog/customizing-combobox-popups https://undocumentedmatlab.com/blog/customizing-combobox-popups#comments Wed, 24 Sep 2014 12:01:07 +0000 http://undocumentedmatlab.com/?p=5056
 
Related posts:
  1. Editbox data input validation Undocumented features of Matlab editbox uicontrols enable immediate user-input data validation...
  2. Continuous slider callback Matlab slider uicontrols do not enable a continuous-motion callback by default. This article explains how this can be achieved using undocumented features....
  3. Matlab and the Event Dispatch Thread (EDT) The Java Swing Event Dispatch Thread (EDT) is very important for Matlab GUI timings. This article explains the potential pitfalls and their avoidance using undocumented Matlab functionality....
  4. Tri-state checkbox Matlab checkboxes can easily be made to support tri-state functionality....
 
]]>
Last week I explained how we can use display custom items in a standard Matlab combobox (popup/dropdown), using its underlying Java component. Today I will show how we can use this Java component for other nice customizations of the combobox’s popup:

Underlying Java component

The first step is to find the underlying Java component of the Matlab combobox (aka popup) uicontrol. This is done using my findjobj utility:

% Create the Matlab combobox
items = {'<HTML><FONT color="red">Hello</Font></html>', 'world', ...
         '<html><font style="font-family:impact;color:green"><i>What a', ...
         '<Html><FONT color="blue" face="Comic Sans MS">nice day!</font>'};
hCombobox = uicontrol('Style','popup', 'Position',[10,100,120,20], 'String',items);
 
% Find the uicontrol's underlying Java component
jCombobox = findjobj(hCombobox);

For findjobj to work, the Matlab uicontrol needs to be visible – it will not have a Java component before it is rendered onscreen for the first time. If everything is successful, jCombobox should now be a reference to the underlying om.mathworks.hg.peer.ComboboxPeer$MLComboBox Java component, which is an extension of the standard Swing JComboBox, as can be seen using my checkClass utility:

>> jCombobox.checkClass
 
private com.mathworks.hg.peer.ComboboxPeer$MLComboBox (uiinspect)
 
Superclass: com.mathworks.mwswing.MJComboBox
Superclass: javax.swing.JComboBox
 
Methods in JComboBox missing in ComboboxPeer$MLComboBox:
   JComboBox()
   JComboBox(java.lang.Object[])
   JComboBox(java.util.Vector)
   JComboBox(javax.swing.ComboBoxModel)
 
Methods in ComboboxPeer$MLComboBox missing in JComboBox:
   ComboboxPeer$MLComboBox(com.mathworks.hg.peer.ComboboxPeer)
   isPopupWidthConstrained() : boolean
   isTipWhenTruncatedEnabled() : boolean
   processEvent(java.awt.AWTEvent)
   registerWithKeyBindingManager(com.mathworks.mwswing.binding.KeyBindingManager, java.lang.String)
   setConstrainPopupWidth(boolean)
   setEditorColumnCount(int)
   setTipWhenTruncatedEnabled(boolean)
 
Methods inherited & modified by ComboboxPeer$MLComboBox:
   getInsets() : java.awt.Insets
   setBackground(java.awt.Color)
   updateUI()
 
Interfaces in JComboBox missing in ComboboxPeer$MLComboBox:
   java.awt.ItemSelectable
   java.awt.event.ActionListener
   javax.accessibility.Accessible
   javax.swing.event.ListDataListener

We shall now use three properties of this object to customize the control’s popup:

MaximumRowCount

The MaximumRowCount numeric property (default=20) sets the maximal number of drop-down items to display in the visible portion of the popup, before requiring a scrollbar. This basically controls the popup’s height:

% Get the current MaximumRowCount value 
numItems = get(jCombobox, 'MaximumRowCount');
numItems = jCombobox.MaximumRowCount;     % equivalent - access the property directly
numItems = jCombobox.getMaximumRowCount;  % equivalent - use Java's accessor method (best way)
 
% Set the MaximumRowCount value
set(jCombobox,'MaximumRowCount',3);
jCombobox.MaximumRowCount = 3;      % equivalent - access the property directly
jCombobox.setMaximumRowCount(3);    % equivalent - use Java's accessor method (best way)

MaximumRowCount=20 (default)

MaximumRowCount=20
(default)

MaximumRowCount=3

MaximumRowCount=3
 

MaximumRowCount=2

MaximumRowCount=2
 

Note that MaximumRowCount is a Matlab extension to the standard Swing JComboBox, so if we use a JComboBox directly in our code (using javacomponent) we will not have this feature. Creating the ComboboxPeer$MLComboBox component instead is possible, but is beyond the scope of this article, because MathWorks chose for this class not to have JComboBox‘s standard constructors but rather only a constructor that accepts a com.mathworks.hg.peer.ComboboxPeer object.

PopupVisible

The PopupVisible property (default=false) is a boolean flag which controls whether the popup window is currently (or should be) displayed. If this property is updated, then the focus is automatically transferred to the popup window for easy item selection using the keyboard (up/down/enter keys). There are also equivalent convenience methods showPopup()/hidePopup():

% Is the popup currently shown?
isShown = get(jCombobox, 'PopupVisible');
isShown = jCombobox.PopupVisible;     % equivalent - access the property directly
isShown = jCombobox.isPopupVisible;   % equivalent - use Java's accessor method (best way)
 
% Display the popup
set(jCombobox,'PopupVisible',true);   % NOT 'on' - this is a Java property, not a Matlab HG one!
jCombobox.PopupVisible = true;        % equivalent - access the property directly
jCombobox.setPopupVisible(true);      % equivalent - use Java's accessor method (best way)
jCombobox.showPopup();                % equivalent - use Java's direct method
 
% Hide the popup
set(jCombobox,'PopupVisible',false);  % NOT 'off' - this is a Java property, not a Matlab HG one!
jCombobox.PopupVisible = false;       % equivalent - access the property directly
jCombobox.setPopupVisible(false);     % equivalent - use Java's accessor method (best way)
jCombobox.hidePopup();                % equivalent - use Java's direct method

Note that PopUpVisible is not a Matlab extension – it exists in the original Swing JComboBox. Unfortunately, it was not included in the list of properties that are exposed to the user by the high-level Matlab uicontrol, so we need to use the underlying Java component.

On a Windows platform the PopupVisible property is toggled, thereby showing/hiding the popup window, whenever the user clicks <Alt-Up> or <Alt-Down> when the combo-box has focus.

PopupWidthConstrained

The PopupWidthConstrained property (default=false) is a boolean flag which is another Matlab extension to the standard Swing JComboBox. It is apparently used to constrain the width of the drop-down list to the width of the text field. MathWorks took the trouble to add this feature because Swing JComboBox‘s width is constrained, causing a difficulty in distinguishing between popup values when the control is relatively narrow; Matlab’s MJComboBox‘s default unconstrained behavior is much more user-friendly:

PopupWidthConstrained=false (default)

PopupWidthConstrained=false
(default)

PopupWidthConstrained=true

PopupWidthConstrained=true
 

Note that the PopupWidthConstrained property’s read accessor methods is the expected isPopupWidthConstrained(), thereby also enabling the expected Matlab-standard format of get(‘PopupWidthConstrained’). However, the property update accessor method is not the expected setPopupWidthConstrained(flag) but rather a non-standard setConstrainPopupWidth(flag). For this reason, it is impossible to set this property using set(‘PopupWidthConstrained’,…), but only via the Java setConstrainPopupWidth() accessor method:

>> set(jCombobox,'PopupWidthConstrained',true)
??? Changing the 'PopupWidthConstrained' property of javahandle_withcallbacks.com.mathworks.hg.peer.ComboboxPeer$MLComboBox is not allowed.
 
>> jCombobox.setPopupWidthConstrained(true)
??? No appropriate method or public field setPopupWidthConstrained for class javahandle_withcallbacks.com.mathworks.hg.peer.ComboboxPeer$MLComboBox.
 
>> jCombobox.setConstrainPopupWidth(true)  % this is ok

For additional customizations of Matlab comboboxes, refer to section 6.7 of my Matlab-Java programming book.

R2014b

We’re all eagerly awaiting the much-anticipated R2014b release. As you all know, this is an important release with major functionality and engine improvements. It is therefore not surprising that the release date (which should normally have been September 1) is somewhat delayed. MathWorkers are hard at work fixing problems in the pre-release beta. This delay was actually anticipated, as can be seen from the pre-release expiry date.

We should all be patient and let MathWorks fix these issues without pressure. This release could be a real home-run and MathWorks should do all it can to ensure that it works as transparently and as backward-compatible as possible so that it indeed becomes a home run rather than an outfield foul ball. Let’s not have a repeat of R2010b, which required two separate service-pack updates. I urge MathWorks to take their time – better safe than sorry. I urge everyone else to be patient – it’s worth the wait.

When 14b is finally out, I will be here with a planned series of articles explaining how we can make good use of all its new goodies. Start drooling…

Happy Jewish New Year everybody!

]]>
https://undocumentedmatlab.com/blog/customizing-combobox-popups/feed 8
Customizing listbox/combobox itemshttps://undocumentedmatlab.com/blog/customizing-listbox-combobox-items https://undocumentedmatlab.com/blog/customizing-listbox-combobox-items#comments Wed, 17 Sep 2014 22:01:34 +0000 http://undocumentedmatlab.com/?p=5029
 
Related posts:
  1. UISplitPane UISplitPane was recently chosen as Matlab Central's Pick of the Week. Here I detail its use of some undocumented Matlab features....
  2. Additional uicontrol tooltip hacks Matlab's uicontrol tooltips have several limitations that can be overcome using the control's underlying Java object....
  3. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  4. The javacomponent function Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...
 
]]>
Last week I wrote about using a variety of techniques to customize listbox items with an attached checkbox icon. Some of these methods used a standard Matlab listbox uicontrol, others used other controls. Today I wish to extend the discussion and show how Matlab listbox and combobox (pop-up) items can be customized in a variety of ways.

To add icons to listbox/combobox items, we could use standard HTML, as I’ve shown last week. This is the simplest method, requires no Java knowledge, and it usually works well. The problem is that when a listbox/combobox has numerous items (hundreds or more), it may start getting sluggish. In such case it is faster to use a dedicated Java cell-renderer that sets the icon, font, colors, tooltip and other aspects on an item-by-item basis. This runs faster and enables far greater customizability than what is possible with HTML. The drawback is that it requires some Java programming. No free lunch…

Listbox and combobox cell-renderers need to extend javax.swing.ListCellRenderer, similarly to uitable cell-renderers. This is basically a simple Java class that minimally contains just an empty constructor and a getListCellRendererComponent() method with a predefined signature. getListCellRendererComponent() is automatically called by the Swing render engine separately for each listbox item, and gets as input args a JList reference, the item value (typically a string), an integer list index, a boolean flag indicating whether the item is currently selected, and another flag indicating whether the item is currently in focus. getListCellRendererComponent() uses these parameters to customize and return a java.awt.Component, which is typically (but not necessarily) a standard Swing JLabel.

Here is a simple example that displays a folder of icon files in a Matlab listbox and combobox. Each item is the filename, with a customization that if the file is an icon, then this icon is displayed next to the file name, otherwise the name appears in red italic without an icon. For illustration, we’ll use Matlab’s builtin icons folder: %matlabroot%/toolbox/matlab/icons/:

Custom listbox cell-renderer    Custom combobox cell-renderer

Creating the cell renderer

We start by creating a custom ListCellRenderer. Place the following code in a file called LabelListBoxRenderer.java:

import java.awt.*;
import javax.swing.*;
import java.util.Hashtable;
 
public class LabelListBoxRenderer extends JLabel implements ListCellRenderer
{
    private String folderPath;
    private final Hashtable<String,ImageIcon> iconsCache = new Hashtable<String,ImageIcon>();
 
    // Class constructors
    public LabelListBoxRenderer() {
        setOpaque(true);
        setHorizontalAlignment(LEFT);
        setVerticalAlignment(CENTER);
    }
    public LabelListBoxRenderer(String folderPath) {
        this();
        this.folderPath = folderPath;
    }
 
    // Return a label displaying both text and image.
    public Component getListCellRendererComponent(
            JList list,
            Object value,
            int index,
            boolean isSelected,
            boolean cellHasFocus)
    {
        String label = value.toString();
        setFont(list.getFont());
        if (isSelected) {
            // Selected cell item
            setBackground(list.getSelectionBackground());
            setForeground(list.getSelectionForeground());
        } else {
            // Unselected cell item
            setBackground(list.getBackground());
            setForeground(list.getForeground());
        }
        try {
            String iconFname = (folderPath + "/" + label).replace('\\', '/');
            ImageIcon icon = getFileIcon(iconFname);
            setIcon(icon);
            if (icon.getIconWidth() > 0) {
                // Cell item is a valid icon filename
                list.setToolTipText(iconFname + " (" + icon.getIconWidth() + " x " + icon.getIconHeight() + ")");
            } else {
                // Cell item is not an icon filename
                list.setToolTipText(iconFname + " (not an icon)");
                setFont(getFont().deriveFont(Font.ITALIC));
                setForeground(Color.red);
            }
        } catch (Exception e) {
            list.setToolTipText(e.getMessage());
        }
        //System.out.println(index + ": " + label);  // debug console printout
        setText(label);
        return this;
    }
 
    // Modify the folder path (default = current folder)
    public void setFolderPath(String folderPath) {
        this.folderPath = folderPath;
    }
 
    // Lazily load the file icons only as needed, later reuse cached data
    private ImageIcon getFileIcon(String filename) {
        ImageIcon icon;
        if (iconsCache.containsKey(filename)) {
            // Reuse cached data
            icon = iconsCache.get(filename);
        } else {
            // Lazily load the file icons only as needed
            icon = new ImageIcon(filename);
            iconsCache.put(filename, icon);  // store in cache for later use
        }
        return icon;
    }
}

In the code above, I’ve cached the ImageIcons, so that the actual disk file is only accessed once rather than repeatedly whenever the cell needs to be rendered. For even improved performance, we could also cache the tooltips and derived italic font so that they would not be regenerated each time (note that the list’s font is not the same as the cell component’s font) – I will leave this as an exercise to the reader.

Next, compile this file (using the standard javac compiler or any Java IDE), ensuring that you target a JVM compatible with your Matlab (JVM 5 will work on R14SP2 onward, 6 on R2007b onward, and 7 only on R2013b or newer). For convenience, both the source and compiled files for the LabelListBoxRenderer class can be downloaded here: LabelListBoxRenderer.java, LabelListBoxRenderer.class.

Using the cell-renderer in Matlab listboxes

Now that we have a custom cell renderer, we should add the LabelListBoxRenderer.class file to Matlab’s Java classpath using the javaaddpath function and then use this class in Matlab:

% Create the Matlab listbox
iconsFolder = fullfile(matlabroot, 'toolbox/matlab/icons');
files = dir(iconsFolder);
hListbox = uicontrol('Style','list', 'String',{files.name}, 'Position',[10,10,120,150]);
 
% Find the uicontrol's underlying Java component
jScrollpane = findjobj(hListbox);
jListbox = jScrollpane.getViewport.getView;
 
% Update the listbox's cell-renderer
javaaddpath 'C:\Yair\Undocumented Matlab\Work\'   % location of my LabelListBoxRenderer.class
jRenderer = LabelListBoxRenderer(iconsFolder);
jListbox.setCellRenderer(jRenderer);
 
% Give the icons some space...
jListbox.setFixedCellHeight(18);

Custom listbox cell-renderer

Wasn’t too painful was it?

Using the cell-renderer in Matlab combo-boxes

Customizing Matlab combo-boxes is just as easy, and uses the same LabelListBoxRenderer class:

% Create the Matlab combobox
iconsFolder = fullfile(matlabroot, 'toolbox/matlab/icons');
files = dir(iconsFolder);
hCombobox = uicontrol('Style','popup', 'String',{files.name}, 'Position',[10,10,120,150]);
 
% Find the uicontrol's underlying Java component
jCombobox = findjobj(hCombobox);  % no scroll-pane for combos
 
% Update the combobox's cell-renderer
javaaddpath 'C:\Yair\Undocumented Matlab\Work\'   % location of my LabelListBoxRenderer.class
jRenderer = LabelListBoxRenderer(iconsFolder);
jCombobox.setRenderer(jRenderer);  % Note: not setCellRenderer()
 
% Give the icons some space...
jCombobox.setFixedCellHeight(18);
 
% Make the drop-down list shorter than the default (=20 items)
jCombobox.setMaximumRowCount(8);

Custom combobox cell-renderer

For additional aspects of listbox and combobox customizations, refer to sections 6.6 and 6.7 of my Matlab-Java programming book.

]]>
https://undocumentedmatlab.com/blog/customizing-listbox-combobox-items/feed 2
CheckboxListhttps://undocumentedmatlab.com/blog/checkboxlist https://undocumentedmatlab.com/blog/checkboxlist#comments Wed, 10 Sep 2014 18:00:55 +0000 http://undocumentedmatlab.com/?p=5012
 
Related posts:
  1. Tri-state checkbox Matlab checkboxes can easily be made to support tri-state functionality....
  2. Matlab and the Event Dispatch Thread (EDT) The Java Swing Event Dispatch Thread (EDT) is very important for Matlab GUI timings. This article explains the potential pitfalls and their avoidance using undocumented Matlab functionality....
  3. Advanced JIDE Property Grids JIDE property grids can use complex cell renderer and editor components and can signal property change events asynchronously to Matlab callbacks...
  4. Color selection components Matlab has several internal color-selection components that can easily be integrated in Matlab GUI...
 
]]>
Several years ago I blogged about using a checkbox-tree in Matlab. A few days ago there was a question on the Matlab Answers forum asking whether something similar can be done with Matlab listboxes, i.e. add checkboxes next to each list item. There are actually several alternatives for this and I thought this could be a good opportunity to discuss them:

MathWorks CheckBoxList

MathWorks CheckBoxList


The HTML image variant

The simplest alternative is to use small icon images checked and unchecked as part of the listbox item labels. As I explained last year, listboxes (like all other Matlab uicontrols that rely on underlying Java Swing components), support HTML and can be formatted using HTML images. For example:

Matlab listbox with HTML image icons

Matlab listbox with HTML image icons

In order to check/uncheck items in the listbox, we can trap the underlying Java component’s MouseClickedCallback using the findjobj utility:

% Assume checked.gif, unchecked.gif are 16x16 icons
prefix = ['<html><img src="file:///' strrep(path_of_icon_files),'\','/') '/unchecked.gif" height=16 width=16 />'];
sampleData = strcat(prefix, {'first', 'Second', 'Third', 'and last'});  % all items are unchecked at first
hListbox = uicontrol(...);
jScrollPane = findjobj(hListbox);
jListbox = handle(jScrollPane.getViewport.getView, 'CallbackProperties');
jListbox.MouseClickedCallback = {@mouseClickedFcn,hListbox};
 
function mouseClickedFcn(jListbox, jEventData, hListbox)
   % Get the clicked item and row index
   clickedX = jEventData.getX;
   clickedY = jEventData.getY;
   if clickedX > 15,  return;  end  % did not click a checkbox so bail out
   clickedRow = jListbox.locationToIndex(java.awt.Point(clickedX,clickedY)) + 1;  % Matlab row index = Java row index+1
   if clickedRow <= 0,  return;  end  % clicked not on an item - bail out
   strs = get(hListbox,'String');
   clickedItem = strs{clickedRow};
 
   % Switch the icon between checked.gif <=> unchecked.gif
   if strfind(clickedItem,'unchecked')
       strs{clickedRow} = strrep(clickedItem,'unchecked','checked');
   else
       strs{clickedRow} = strrep(clickedItem,'checked','unchecked');
   end
   set(hListbox,'String',strs);  % update the list item
end

Finally, when we process the selected list item(s), we can simply check whether they contain ‘unchecked.gif’ or ‘checked.gif’. Pretty straight-forward stuff.

MathWorks CheckBoxList

com.mathworks.mwswing.checkboxlist.CheckBoxList is a JList extension that displays a list of labels in a list with a checkbox next to each label. The labels’ checkboxes can be set, unset and queried using methods supplied by the CheckBoxList class or its com.mathworks.mwswing.checkboxlist.DefaultListCheckModel model:

% First create the data model
jList = java.util.ArrayList;  % any java.util.List will be ok
jList.add(0,'First');
jList.add(1,'Second');
jList.add(2,'Third');
jList.add(3,'and last');
 
% Next prepare a CheckBoxList component within a scroll-pane
jCBList = com.mathworks.mwswing.checkboxlist.CheckBoxList(jList);
jScrollPane = com.mathworks.mwswing.MJScrollPane(jCBList);
 
% Now place this scroll-pane within a Matlab container (figure or panel)
[jhScroll,hContainer] = javacomponent(jScrollPane,[10,10,80,65],gcf);
 
% Update some items' state programmatically
jCBModel = jCBList.getCheckModel;
jCBModel.checkAll;
jCBModel.uncheckIndex(1);
jCBModel.uncheckIndex(3);
 
% Respond to checkbox update events
jhCBModel = handle(jCBModel, 'CallbackProperties');
set(jhCBModel, 'ValueChangedCallback', @myMatlabCallbackFcn);

This results in the following image:

MathWorks CheckBoxList

MathWorks CheckBoxList

We can query the various checked/unchecked states programmatically:

>> jCBList.getCheckedValues
ans =
[First, Third]
 
>> jCBList.getCheckedIndicies'
ans =
           0       2
 
>> jCBModel.isIndexChecked(0)
ans =
     1    % =true

JIDE’s CheckBoxList

There is also an unrelated JIDE equivalent: com.jidesoft.swing.CheckBoxList. Readers are referred to the JIDE documentation for additional details.

The basic idea is the same as with the MathWorks CheckBoxList: we create the data model, then create a CheckBoxList component within a JScrollPane and place this onscreen using the javacomponent function. We can then modify or query the data model programmatically, and set various callback functions to process user events.

% Prepare the data model as above
 
% Now display onscreen:
jCBList = com.jidesoft.swing.CheckBoxList(jList.toArray)
jScrollPane = com.mathworks.mwswing.MJScrollPane(jCBList);
[jhScroll,hContainer] = javacomponent(jScrollPane, [120,10,80,65], gcf);
 
% Do some programmatic updates:
jCBList.selectAll;  % reverse: jCBList.selectNone
jCBList.setCheckBoxListSelectedIndices([0,2]);

The appearance is very similar to the MathWorks CheckBoxList, except that JIDE’s CheckBoxList has slightly less space between the list rows, and between the checkboxes and labels. The main difference between these components is not in their visual appearance but rather in their supported functionalities (internal methods) – some people might prefer the MathWorks component, others might like JIDE better. To see these functionalities, use my uiinspect and/or checkClass utilities.

For additional information on the MathWorks and JIDE components, and how to investigate and customize them, see Chapter 5 of my Matlab-Java programming book.

ActiveX and other alternatives

If you are running on Windows, you could use ActiveX controls that implement checkbox list functionality. One such control that is pretty standard is Microsoft’s MSComctlLib.ListViewCtrl.2. I showed an example of ListViewCtrl usage a few years ago, and readers are referred there for details. Here is the end result:

Sorted ListViewCtrl

Sorted ListViewCtrl

Granted, this is more of a table having a checkbox column than a listbox, but you can easily make the ListViewCtrl have only a single column.

In addition to this standard ListViewCtrl control, there are plenty of other third-party ActiveX or Java controls that can more-or-less easily be integrated in our Matlab GUI. The drawback of ActiveX is that it only works on a limited set of platforms, whereas the Java-based components (either MathWorks or JIDE) work on all Matlab installations.

Matlab uitable in disguise

As a variant of the idea of using a table with a checkbox first column, we could use Matlab’s builtin uitable function, as suggested by Sebastian below. Here is a simple code snippet illustrating this idea:

data = {true,'First'; false,'Second'; true,'Third'; false,'and last'};
hTable = uitable('Data',data,'RowName',[],'ColumnName',[],'BackgroundColor',[1,1,1],'Position',[10,10,100,70],'ColumnWidth',{20,60});

Matlab uitable with checkbox column

Matlab uitable with checkbox column

Anyway, let no one say ever again that Matlab GUI is boring. It is not. It is only limited by our imagination and our willingness to find and customize components that implement our requirements. There are plenty of alternatives out there, we just need to reach out and use them. If you can’t do it yourself, you could always use an external consultant like me to help you.

]]>
https://undocumentedmatlab.com/blog/checkboxlist/feed 19
Undocumented button highlightinghttps://undocumentedmatlab.com/blog/undocumented-button-highlighting https://undocumentedmatlab.com/blog/undocumented-button-highlighting#respond Wed, 05 Feb 2014 16:00:48 +0000 http://undocumentedmatlab.com/?p=4635
 
Related posts:
  1. Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
  2. Rich-contents log panel Matlab listboxes and editboxes can be used to display rich-contents HTML-formatted strings, which is ideal for log panels. ...
  3. Aligning uicontrol contents Matlab uicontrols can often be customized using plain HTML/CSS, without need for advanced Java. ...
  4. Multi-line uitable column headers Matlab uitables can present long column headers in multiple lines, for improved readability. ...
 
]]>
One of my consulting clients approached me yesterday with a mystery: In his GUIDE-generated GUI, one of the buttons had a bluish tint, and no obvious property seemed to control this or to differentiate it from its sibling controls. Here’s a parred-down version of his GUI:

Highlighted GUI button

Highlighted GUI button

So while it was very nice to have a highlighted button in this manner, the fact that he did not know why it happened and how to control it was a bit unsettling. Which is where I came in, and it turns out that the solution to the mystery is simple and very easy to use. My client now happily switches button highlights on and off, just for the fun of it…

Before I describe the solution (spoiler alert: scroll down), I think it is instructional to understand the unsuccessful attempts, so here goes:

Various alternatives

Our first attempts to understand the situation were to modify the button control’s obvious suspect properties:

  • String – the button had an HTML label. One might presume that this caused the highlighting tint, perhaps an HTML image painted the background? HTML labels for uicontrols are really cool so it would be a pity to have to stop using them. Fortunately, replacing the HTML label with a simple string had no effect, so we can keep using HTML labels safely and freely. But we’re still left with our mystery, so moving on…
  • Border – yet another suspect: the control’s border and fly-over appearance feature affects its appearance. This also proved a dead-end: all the buttons had simple default borders, nothing special about the highlighted one.
  • Background – another dead end: while we could indeed set a non-standard button color, this property does not enable the tinting effect (lighter half at top, darker at bottom). Needless to say, in our case this property had the default (gray) value.
  • Selected – this property does not really highlight the control, but rather draws a thick dashed border around it (see below).
  • focus – by calling uicontrol(hButton) we can have Matlab set the focus on the button. The Operating System then automatically kicks in to add some shading effect. This finally looked close, but again, it was just not quite right.

Highlight (left); focus (center); Selected (right)

Highlight (left); focus (center); Selected (right)

Solution of the highlighting mystery

So maybe GUIDE attached some funky property value to the control? Let’s investigate. Remembering that the GUIDE-generated *.fig file is simply a standard MAT file with a different extension, we can load it into the Matlab workspace and dissect it. Drilling down the GUI hierarchy we find:

>> data = load('myGUI.fig', '-mat')
data = 
    hgS_070000: [1x1 struct]
 
>> d.hgS_070000.children(9).properties
ans = 
              Units: 'pixels'
           Callback: [function_handle]
           Position: [20 20 60 20]
             String: 'Yes'
              Value: 1    ApplicationData: [1x1 struct]
>> d.hgS_070000.children(10).properties
ans = 
              Units: 'pixels'
           Callback: [function_handle]
           Position: [100 20 60 20]
             String: 'No'
    ApplicationData: [1x1 struct]

When we compare the information that GUIDE stored for the two buttons we see that it stored an extra Value property for the ‘Yes’ button, and used the default HG value for the ‘No’ button. Let’s compare the property values in run-time (I’m using my objDiff utility for this):

>> hButton1 = findall(gcf, 'String', 'Yes');
>> hButton2 = findall(gcf, 'String', 'No');
>> props1 = get(hButton1);
>> props2 = get(hButton2);
>> objdiff(props1, props2)
ans = 
      Extent: {[0 0 24 19]  [0 0 17 19]}
    Position: {[20 20 60 20]  [100 20 60 20]}
      String: {'Yes'  'No'}
       Value: {[1]  [0]}

This pretty much nails it: pushbutton highlighting is controlled via the Value property. According to the official documentation, the Value property has no meaning for push-buttons, only for other uicontrol styles. This is obviously not so:

set(hButton, 'Value', 1);   % Turn button highlighting on
set(hButton, 'Value', 0);   % Turn button highlighting off (can use any value ~=1)

Under the hood

Under the hood, updating the Value property sets the pushbutton’s underlying Java control‘s Selected property to true. Note that the Java Selected property is entirely unrelated to Matlab’s Selected property (which has no underlying Java counterpart). I do not understand the design decision that let to this, but since it has been like this for many years I see little chance that it will be changed in the near future.

In any case, the Java Selected property indeed has a visual effect, but the actual effect depends on the current operating system and Look-&-Feel (LnF). You can play around with the LnF to achieve various other alternative highlighting effects, or customize one of your own.

Advanced Matlab GUI course – London 12-14 March, 2014

If this topic has piqued your interest, consider joining my Advanced Matlab GUI course in London on 12-14 March, 2014. In this course/seminar I will explore numerous other ways by which we can customize Matlab’s GUI and graphics in ways that you never knew were even possible! This is a unique opportunity to take your Matlab skills to a higher level within just a few days. This training is not offered anywhere else.

]]>
https://undocumentedmatlab.com/blog/undocumented-button-highlighting/feed 0
Listbox layout customizationhttps://undocumentedmatlab.com/blog/listbox-layout-customization https://undocumentedmatlab.com/blog/listbox-layout-customization#comments Wed, 13 Nov 2013 20:08:28 +0000 http://undocumentedmatlab.com/?p=4374
 
Related posts:
  1. Setting line position in an edit-box uicontrol Matlab uicontrols have many useful features that are only available via Java. Here's how to access them....
  2. Setting listbox mouse actions Matlab listbox uicontrol can be modified to detect mouse events for right-click context menus, dynamic tooltips etc....
  3. Customizing listbox & editbox scrollbars Matlab listbox and multi-line editbox uicontrols have pre-configured scrollbars. This article shows how they can be customized....
  4. Continuous slider callback Matlab slider uicontrols do not enable a continuous-motion callback by default. This article explains how this can be achieved using undocumented features....
 
]]>
I haven’t written on listboxes in a long while, and since I’ve recently posted on related controls (editbox, combo-box), 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. We can get this component’s reference using the findjobj utility:

>> 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: a javax.swing.JViewport that contains the ListboxPeer$UicontrolList component, and horizontal/vertical scrollbars. I explained how to customize the scrollbars 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} = ['<html><img src="file:/' iconFilename '"/>'];  % no need for </html>
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):

  • Customize the scrollbars, as noted above
     
  • Display HTML-formatted list items:
    uicontrol('Style','list', 'Position',[10,10,70,70], 'String', ...
       {'<html><font color="red">Hello</font></html>', 'world', ...
        '<html><font style="font-family:impact;color:green"><i>What a', ...   % note: </i></font></html> are not needed
        '<html><font color="blue" face="Comic Sans MS">nice day!</font>'});   % note: </html> is not needed

    Listbox with HTML'ed items

    Listbox with HTML colored items

  • Setting dynamic tooltips and right-click context-menus:
    Listbox dynamic tooltip

    Listbox dynamic tooltip

       
    Listbox dynamic context (right-click) menu

    Listbox dynamic context (right-click) menu

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 ($39, 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.

If you’d like me to personally add similar magic to your GUI, email me 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? :-)

]]>
https://undocumentedmatlab.com/blog/listbox-layout-customization/feed 6
Editable combo-boxhttps://undocumentedmatlab.com/blog/editable-combo-box https://undocumentedmatlab.com/blog/editable-combo-box#comments Wed, 09 Oct 2013 15:38:55 +0000 http://undocumentedmatlab.com/?p=4246
 
Related posts:
  1. The javacomponent function Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...
  2. Adding a context-menu to a uitree uitree is an undocumented Matlab function, which does not easily enable setting a context-menu. Here's how to do it....
  3. Customizing Matlab labels Matlab's text uicontrol is not very customizable, and does not support HTML or Tex formatting. This article shows how to display HTML labels in Matlab and some undocumented customizations...
  4. GUI integrated HTML panel Simple HTML can be presented in a Java component integrated in Matlab GUI, without requiring the heavy browser control....
 
]]>
In previous articles, I explained how we can use findjobj to customize a Matlab uicontrol’s underlying Java control, thereby improving its appearance and functionality. My two previous articles 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:

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

Lesson learnt

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

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 ($39, 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.

]]>
https://undocumentedmatlab.com/blog/editable-combo-box/feed 19
Editbox data input validationhttps://undocumentedmatlab.com/blog/editbox-data-input-validation https://undocumentedmatlab.com/blog/editbox-data-input-validation#comments Wed, 02 Oct 2013 14:00:51 +0000 http://undocumentedmatlab.com/?p=4229
 
Related posts:
  1. Matlab and the Event Dispatch Thread (EDT) The Java Swing Event Dispatch Thread (EDT) is very important for Matlab GUI timings. This article explains the potential pitfalls and their avoidance using undocumented Matlab functionality....
  2. 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....
  3. Continuous slider callback Matlab slider uicontrols do not enable a continuous-motion callback by default. This article explains how this can be achieved using undocumented features....
  4. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
 
]]>
Last week I explained how Matlab’s editbox control can be customized using its underlying Java component. Today I extend that article by explaining how we can use this information to provide a very user-friendly input-validation function for Matlab editboxes.

Zip-code entry validation example

Zip-code entry validation example


As before, we first need to get the Matlab control’s underlying Java control. This is done using the findjobj utility:

% Prepare the log editbox
hEditbox = uicontrol('Style','edit', 'String','Matlab', ...);
 
% Get the underlying Java editbox
jEditbox = findjobj(hLogPanel);
 
try
    % Multi-line editboxes are contained within a scroll-panel
    jEditbox = handle(jEditbox.getViewport.getView, 'CallbackProperties');
catch
    % probably a single-line editbox
end

Callbacks

Once we have the jEditbox reference handle, we can use some ~30 different event callbacks that it exposes. Some of the useful callbacks include:

  • ActionPerformedCallback – fired when <enter> is clicked in the editbox
  • CaretUpdateCallback – fired when the caret position has changed
  • KeyTypedCallback – fired whenever a keyboard button is typed when the editbox has focus

For example:

set(jEditbox, 'KeyPressedCallback',@myValidationFunction);
 
% Callback function definition
function myValidationFunction(jEditbox, eventData)
    % The following comments refer to the case of Alt-Shift-b
    keyChar = get(eventData,'KeyChar');  % or: eventData.getKeyChar  ==> 'B'
    isAltDown = get(eventData,'AltDown');  % ==> 'on'
    isAltDown = eventData.isAltDown;  % ==> true
    modifiers = get(eventData,'Modifiers');  % or: eventData.getModifiers ==> 9 = 1 (Shift) + 8 (Alt)
    modifiersDescription = char(eventData.getKeyModifiersText(modifiers));  % ==> 'Alt+Shift'
    % (now decide what to do with this key-press...)
end

Using such a validation function enables us to immediately convert typed characters into ‘*’ (in password fields) or check that the input conforms to a standard format such as a 5-digit zip code, a valid-looking email address or a valid-looking credit-card number (Luhn’s algorithm, recently featured in a video tutorial by Doug Hull). Of course, there are dedicated JIDE controls that do much of this already, but let’s not digress.

In today’s example, we shall implement a simple input-validation function for a 5-digit zip code. When the input data is invalid, the editbox will be colored red and an appropriate message will appear next to the editbox. In addition, invalid (non-digit) characters shall be rejected with a beep sound.

Zip-code validation example

To illustrate the above, let’s use an example of a 5-digit zip-code entry validation. We start by creating an empty editbox with an associated message label next to it:

figure('Color','w', 'Menubar','none');
hEditbox = uicontrol('Style','edit', 'Pos',[10,10,60,20], 'String','Matlab');  % start with an invalid string
hMessageLabel = uicontrol('Style','text', 'Pos',[80,10,200,20], 'horizontal','left', 'background','w', 'Foreground','red');

Next we get the underlying jEditbox reference and set its entry-validation callback function:

jEditbox = findjobj(hEditbox);  % single-line editbox so there's need to drill-down the scroll-pane
set(jEditbox, 'KeyPressedCallback',{@editboxValidation,hMessageLabel});

Note how we pass the message-label’s handle as an extra input parameter to the callback function.

Now we define the callback function editboxValidation and place it on the Matlab path (for example, by placing the following within editboxValidation.m in a folder that is already on your path):

% editboxValidation - ensure that an editbox input is a valid 5-digit zip code
function editboxValidation(jEditbox, eventData, hMessageLabel)
    keyChar = eventData.getKeyChar;  % see note below about how we can trick Matlab here
    if ~alldigits(keyChar) && isprintable(keyChar)
        beep;
        fixedText = strrep(char(jEditbox.getText), keyChar, '');
        jEditbox.setText(fixedText);
    end
    updateAppearance(jEditbox, hMessageLabel);
end
 
% Check whether a string only contains digits
function flag = alldigits(str)
    flag = ~isnan(str2double(str));
end
 
% Check whether a character is printable
function flag = isprintable(keyChar)
    keyVal = double(keyChar);
    flag = ~isempty(keyVal) && keyVal > 31 && keyVal < 128;
end
 
% Update the GUI appearance based on the editbox text
function updateAppearance(jEditbox, hMessageLabel)
    currentText = char(jEditbox.getText);
    if isempty(currentText)
        set(hMessageLabel, 'String','Please enter a 5-digit zip-code')
        jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.red, 3, false));
    elseif ~alldigits(currentText)
        beep;
        set(hMessageLabel, 'String','Invalid zip: should only contain digits')
        jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.red, 3, false));
    elseif length(currentText) ~= 5
        set(hMessageLabel, 'String','Invalid zip: should have exactly 5 digits')
        jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.red, 3, false));
    else
        set(hMessageLabel, 'String','');
        jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.gray, 1, false));
    end
end

Finally, we call the validation function directly after creating our GUI, to let the user know that the zip-code needs to be entered:

% Note how we trick Matlab by using eventData as a struct rather than a Java object
% (i.e., getKeyChar is set here to be a simple struct field, rather than a Java method)
eventData.getKeyChar = '';
editboxValidation(jEditbox,eventData,hMessageLabel)

Zip-code entry validation example

Zip-code entry validation example

Naturally, this is a very simple example, and you can easily expand it for your needs. But it does show the basic components of any input validation: checking the new data, updating the control as appropriate, and modifying the appearance of the underlying control and of other associated controls.

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 ($39, 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.

]]>
https://undocumentedmatlab.com/blog/editbox-data-input-validation/feed 4
Customizing editboxeshttps://undocumentedmatlab.com/blog/customizing-editboxes https://undocumentedmatlab.com/blog/customizing-editboxes#comments Wed, 25 Sep 2013 14:00:26 +0000 http://undocumentedmatlab.com/?p=4212
 
Related posts:
  1. Uicontrol callbacks This post details undocumented callbacks exposed by the underlying Java object of Matlab uicontrols, that can be used to modify the control's behavior in a multitude of different events...
  2. Setting listbox mouse actions Matlab listbox uicontrol can be modified to detect mouse events for right-click context menus, dynamic tooltips etc....
  3. Customizing Matlab labels Matlab's text uicontrol is not very customizable, and does not support HTML or Tex formatting. This article shows how to display HTML labels in Matlab and some undocumented customizations...
  4. GUI integrated HTML panel Simple HTML can be presented in a Java component integrated in Matlab GUI, without requiring the heavy browser control....
 
]]>
As a natural follow-up to last week’s article about rich-content log panels (multi-line editbox), today I discuss some additional customizations that can be done to Matlab’s editbox control.

Matlab’s dual editbox controls

There are two distinct uicontrols called ‘editbox’ in Matlab: a single-line editbox and a multi-line editbox. Matlab automatically uses the single-line control if the Max property is set to 1 (the default value, backward compatible with early Matlab versions). If Max > 1, the multi-line editbox is used. Today’s article will focus on features shared by both the single-line and multi-line editbox controls.

Beware of a possible pitfall using Matlab’s editbox controls: when switching styles, including switching between the single-line and multi-line editbox versions, Matlab replaces the underlying Java component with a new component that has default properties. Therefore, if we need any customizations to the uicontrol, then we should ensure that they are done after setting the final uicontrol style, otherwise they will be discarded.

Underlying Java object

As discussed in many prior articles, the first step in customization is to get access to the Matlab control’s underlying Java control. This is done using the findjobj utility:

% Prepare the log editbox
hEditbox = uicontrol('Style','edit', 'String','Matlab', ...);
 
% Get the underlying Java editbox
jEditbox = findjobj(hLogPanel);
 
try
    % Multi-line editboxes are contained within a scroll-panel
    jEditbox = handle(jEditbox.getViewport.getView, 'CallbackProperties');
catch
    % probably a single-line editbox
end

Borders

As I have explained long ago, all uicontrol borders can be customized using the underlying jEditbox handle’s Border property:

% Create a new border
lineColor = java.awt.Color(1,0,0);  % =red
thickness = 3;  % pixels
roundedCorners = true;
newBorder = javax.swing.border.LineBorder(lineColor,thickness,roundedCorners);
 
% Override the default control's border
jEditbox.Border = newBorder;  % or: set(jEditbox,'Border',newBorder) or: jEditbox.setBorder(newBorder)
 
% Remove the border altogether
jEditbox.Border = [];
 
% Redraw the modified control after we have changed its appearance
jEditbox.repaint;

editbox with regular border

editbox with regular border

   
editbox with custom border

editbox with custom border

   
editbox with no border

editbox with no border


Much more complex and interesting borders can be created in much the same way. Interested readers are referred to the official documentation of Java Borders or any decent Swing textbook.

Text selection

Several jEditbox properties control the text-selection functionality:

  • SelectionStart, SelectionEnd control the characters within the displayed text that are selected (typically with some shaded background color). A value of 0 means the first character, 1 means the second character etc. Setting SelectionStart=0 and SelectionEnd=intmax selects the entire text. We can also use jEditbox.select(selectionStart,selectionEnd). For example:
    set(jEditbox, 'SelectionStart',1, 'SelectionEnd',5);
    jEditbox.select(1,5)  % equivalent alternative

    Setting the selected text

    Setting the selected text

  • SelectionColor, SelectedTextColor change the foreground and background colors of the selected text. These properties are overridden whenever the editbox gains focus, so we need to be override them in the editbox’s FocusGainedCallback:
    cbStr = ['set(gcbo,''SelectionColor'',java.awt.Color.red,' ...
                   '''SelectedTextColor'',java.awt.Color.blue)'];
    set(jEditbox, 'FocusGainedCallback', cbStr);

    Non-standard selection colors and FocusGainedCallback

    Non-standard selection colors, FocusGainedCallback

  • SelectedText is a read-only property holding the text currently selected, between the SelectionStart and SelectionEnd positions. Associated property Text holds the entire text within the editbox. Note that both these properties hold a java.lang.String object, which should be cast to a Matlab string via Matlab’s built-in char function, unless we use Matlab’s get function (which does this conversion for us automatically):
    str = char(jEditbox.getSelectedText);
    str = get(jEditbox,'SelectedText');  % equivalent alternative

Customizing the input caret

The Caret property, which is common to all Java Swing data-entry components, references a javax.swing.text.DefaultCaret object that controls the text caret appearance (this is naturally relevant only for editable editboxes).

The caret object has its own properties that can be customized. For example: BlinkRateRate, Visible and UpdatePolicy. The caret’s StateChangedCallback is invoked whenever the caret position is updated.

Some additional caret-related properties can be set using jEditbox properties: CaretColor and CaretPosition (which uses 0-based, like SelectionStart and SelectionEnd above). Here is an example that modifies the default caret color to something a bit more lively:

% Set the caret color to red
jEditbox.setCaretColor(java.awt.Color(1.0,0,0));
jEditbox.setCaretColor(java.awt.Color.red);	% an alternative

Red CaretColor

Red CaretColor

Behavior

Several properties of the jEditbox handle control the editbox behavior beyond what is available by the Matlab uicontrol:

  • Editable – (default=true) a boolean flag indicating whether or not the editbox text can be modified. Note that the Matlab HG handle (hEditbox) only allows setting the Enable property (its jEditbox Java counterpart property is called Enabled), but not to set an enabled yet uneditable control – this can only be done using the Java Editable property.
  • DisabledTextColor controls the text color (default=gray) when the editbox is disabled.
  • DragEnabled – (default=false) a boolean flag indicating whether the editbox contents can be mouse-dragged externally as a DND source (for example, onto an editor, command line or any DND target). The DropMode, DropLocation, DropTarget and TransferHandler properties enable the editbox act as a DND target, accepting externally-dragged data as input sources.
  • FocusAccelerator – (default=char(0)) sets the keyboard accelerator sequence that will cause the receiving text component to get the focus. The accelerator will be the key combination of the <Alt> key and the specified character, converted to upper-case. Any previous key accelerator setting, including menu-bar accelerators, will be superseded. A char(0) key has the effect of turning off the focus accelerator. By default, there is no focus accelerator key (i.e., an accelerator of \0=char(0)). For example, let us set the accelerator to <Alt>-E, overriding the menu-bar’s default accelerator for the Edit menu:
    >> jEditbox.setFocusAccelerator('e');
    >> jEditbox.getFocusAccelerator		% let us check...
    ans =
    E	% 'e' converted to 'E', meaning an Alt-E accelerator

Additional editbox behavior can be customized using the dozens of callback functions that jEditbox exposes. These callbacks enable modifying the appearance and behavior of the editbox based on events such as mouse movements (into/over/out-of), focus gain/loss, key-clicks (that enable input data validation) etc. I plan to describe a data input-validation function based on these callbacks, using some of the customizations shown above, in next week’s article.

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 ($39, 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.

]]>
https://undocumentedmatlab.com/blog/customizing-editboxes/feed 4
Rich-contents log panelhttps://undocumentedmatlab.com/blog/rich-contents-log-panel https://undocumentedmatlab.com/blog/rich-contents-log-panel#comments Wed, 18 Sep 2013 14:00:16 +0000 http://undocumentedmatlab.com/?p=4180
 
Related posts:
  1. Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
  2. Aligning uicontrol contents Matlab uicontrols can often be customized using plain HTML/CSS, without need for advanced Java. ...
  3. Multi-line uitable column headers Matlab uitables can present long column headers in multiple lines, for improved readability. ...
  4. Images in Matlab uicontrols & labels Images can be added to Matlab controls and labels in a variety of manners, documented and undocumented. ...
 
]]>
I often include a log panel in Matlab applications that process data. By sending messages to the log panel, I can avoid msgbox popups and Command Window messages that interfere with the regular workflow. In Matlab, such log panels typically use a simple listbox or editbox control. The problem with this is that all text messages in the log panel look the same. Matlab does not have a documented way to highlight specific messages or words. Well, this has never stopped us before, has it? :-)

The listbox solution

I have often noted in past articles that most Matlab uicontrols support HTML formatting. We can use a listbox control for our log panel, and use HTML formatting for the various log messages, based on their severity or content. For example:

Listbox with HTML'ed items

Listbox with HTML colored items

uicontrol('Style','list', 'Position',[10,10,70,70], 'String', ...
   {'<html><font color="red">Hello</font></html>', 'world', ...
    '<html><font style="font-family:impact;color:green"><i>What a', ...   % note: </i></font></html> are not needed
    '<html><font color="blue" face="Comic Sans MS">nice day!</font>'});   % note: </html> is not needed

Rich listboxes such as this are very easy to set up and use. As I just showed, all it takes is sending an HTML string to a regular listbox. The down-side is that listboxes only display single-line messages, so if our message is too long we need to manually split it into separate listbox lines, which is rather inconvenient. Using HTML <br/> does not work since the allocated line height remains unchanged. We can fix this by playing around with the underlying Java object‘s RowHeight property, but that again is rather inconvenient.

The editbox solution

Instead of a listbox, I often use a multi-line editbox. Unfortunately, HTML is not as-easy to use in multi-line editbox contents, but as I have shown before, it is indeed possible and actually quite powerful. In fact, I am using such an editbox-based log panel’s in my online presentation at the MATLAB Computational Finance Virtual Conference tomorrow (Thursday Sep 19, 2013 at 2pm EST / 8pm CEST, see details below):

Real-time trading system demo in Matlab (click to zoom)

Real-time trading system demo in Matlab (click to zoom)

We can see in the screenshot that some log messages (the red warning message) can span multiple lines. Moreover, the panels can be interactively dragged/resized, making the multi-line log messages “flow” based on available space. So using an editbox is preferable to a listbox. The solution implemented in the demo is quite simple:

First we define the logging utility function (the icon filenames may need to be changed based on your Matlab release):

function logMessage(jEditbox,text,severity)
   % Ensure we have an HTML-ready editbox
   HTMLclassname = 'javax.swing.text.html.HTMLEditorKit';
   if ~isa(jEditbox.getEditorKit,HTMLclassname)
      jEditbox.setContentType('text/html');
   end
 
   % Parse the severity and prepare the HTML message segment
   if nargin < 3,  severity='info';  end
   switch lower(severity(1))
      case 'i',  icon = 'greenarrowicon.gif'; color='gray';
      case 'w',  icon = 'demoicon.gif';       color='black';
      otherwise, icon = 'warning.gif';        color='red';
   end
   icon = fullfile(matlabroot,'toolbox/matlab/icons',icon);
   iconTxt =['<img src="file:///',icon,'" height=16 width=16/>'];
   msgTxt = ['&nbsp;<font color=',color,'>',text,'</font>'];
   newText = [iconTxt,msgTxt];
   endPosition = jEditbox.getDocument.getLength;
   if endPosition>0, newText=['<br />' newText];  end
 
   % Place the HTML message segment at the bottom of the editbox
   currentHTML = char(jEditbox.getText);
   jEditbox.setText(strrep(currentHTML,[60 '/body>'],newText));
   endPosition = jEditbox.getDocument.getLength;
   jEditbox.setCaretPosition(endPosition); % end of content
end

Next, we initialize the log panel editbox and store the editbox’s underlying Java component (jEditbox) using the findjobj utility:

% Prepare the log editbox
hLogPanel = uicontrol('style','edit', 'max',5, 'Parent',hLeftBottomPanel, 'Units','norm', 'Position',[0,0.2,1,0.8], 'Background','w');
 
% Get the underlying Java editbox, which is contained within a scroll-panel
jScrollPanel = findjobj(hLogPanel);
try
    jScrollPanel.setVerticalScrollBarPolicy(jScrollPanel.java.VERTICAL_SCROLLBAR_AS_NEEDED);
    jScrollPanel = jScrollPanel.getViewport;
catch
    % may possibly already be the viewport, depending on release/platform etc.
end
jEditbox = handle(jScrollPanel.getView,'CallbackProperties');

Now, we can use this logging utility function to log messages in our application. For example:

logMessage(jEditbox, 'a regular info message...');
logMessage(jEditbox, 'a warning message...', 'warn');
logMessage(jEditbox, 'an error message!!!', 'error');
logMessage(jEditbox, 'a regular message again...', 'info');

Rich editbox contents (a log file)

Rich editbox contents (a log file)

HTML editboxes are normally editable, images included. In actual applications, we usually wish to prevent editing the displayed log. To do this, we simply call jEditbox.setEditable(false). Similarly, it is easy to set-up a Matlab callback-function to handle hyperlink clicks in the log panel (unlike what we might think, this is not handled automatically by the HTML processing engine):

% Prevent user editing in the log-panel
jEditbox.setEditable(false);
 
% Set-up a Matlab callback function to handle hyperlink clicks
set(jEditbox,'HyperlinkUpdateCallback',@linkCallbackFcn);

About the MATLAB Computational Finance Virtual Conference and my presentation

The MATLAB Computational Finance Virtual Conference is a one-day (Thursday Sep 19, 2013) event of hour-long presentations by industry professionals that showcase real-world examples demonstrating how financial-industry researchers and developers can excel at their jobs, improve their research and business processes, reduce costs, and mitigate risks by using Matlab. Registration to the conference is free and it’s a virtual conference, so there’s no need for a tie and jacket and you’re welcome to join…

MATLAB Computational Finance Conference 2013

My presentation on “A Real-Time Trading System in MATLAB“, is scheduled for 2pm EST / 8pm CEST. Following a half-hour presentation, I will answer audience questions online. The presentation slides can be downloaded here. Here is the recorded presentation video:

The demo system’s user interface showcases the hidden visualization and interactivity potential of Matlab for tracking order executions and charting financial time-series in real time. The undocumented features used in the demo include:

So, even if you’re not interested in real-time financial trading with Matlab, you might find it interesting to see the neat things that Matlab can do using a Java API interface and a few undocumented GUI tricks (such as the rich-contents log that I explained above).

The demo source code is provided here (tradingDemo.m and supporting files). Note that this is provided as-is, free of charge but without any warranty or support. You would naturally need IB-Matlab and an Interactive Brokers account to run it. But you can reuse parts of the source code in your Matlab programs even without an IB account or IB-Matlab.

]]>
https://undocumentedmatlab.com/blog/rich-contents-log-panel/feed 15
JTattoo look-and-feel demohttps://undocumentedmatlab.com/blog/jtattoo-look-and-feel-demo https://undocumentedmatlab.com/blog/jtattoo-look-and-feel-demo#comments Wed, 20 Mar 2013 16:00:11 +0000 http://undocumentedmatlab.com/?p=3687
 
Related posts:
  1. Additional uicontrol tooltip hacks Matlab's uicontrol tooltips have several limitations that can be overcome using the control's underlying Java object....
  2. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  3. UISplitPane UISplitPane was recently chosen as Matlab Central's Pick of the Week. Here I detail its use of some undocumented Matlab features....
  4. The javacomponent function Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...
 
]]>
Three years ago, I wrote an article about modifying Matlab’s look-and-feel (L&F, or LnF), using Java’s built-in support for replaceable LnFs. To date, that article has 27 comments by 13 different commenters (plus 20 responses by me), making it the second most active article on this website. I decided to follow up on that article with a demo that shows the effects that different L&Fs have on GUI controls, and a demonstration of the JTattoo library of professional L&Fs.

Today’s article and the demo are based on original work by Karthik Ponudurai, who has written a guest article here about an interesting technique to interface a Java GUI to a Matlab application, a couple of years ago.

Demo of using different Look-and-Feels in Matlab GUI

Demo of using different Look-and-Feels in Matlab GUI

JTattoo is a 3rd-party open-source library. The purpose of including it in the demo, in addition to its natural use as a professional set of L&Fs, is to demonstrate how easy it is to integrate 3rd-party L&Fs in Matlab. In the demo I use the current latest available JTattoo library (1.6.7), but you can always download the latest version and replace the JTattoo.jar file. JTattoo contains a large set of different L&Fs that can be used independently (screenshots). The nice thing about L&Fs is that since all Matlab GUI is based on Java Swing, the new L&Fs automatically affect Matlab controls just like native Java ones.

The demo can be downloaded from the Matlab File Exchange. After downloading, unzip it into any folder on your Matlab path and run JTattooDemo.m.

A Matlab figure is displayed with two panels, one containing Matlab uicontrols (within a simple uiflowcontainer) and the other containing Java components.

Two main menus are available: System enables selecting the standard Swing L&Fs that are installed on your system (this varies a bit between platforms and Matlab releases); JTattoo enables selecting one of the JTattoo L&Fs. Once the user selects any of the L&F menu items, the entire figure is updated. This is done by calling javax.swing.SwingUtilities.updateComponentTreeUI() on the figure’s Java Frame‘s content pane. Both the Matlab and the Java controls within the figure are automatically updated by this Swing function to reflect the newly-selected L&F. Care is taken to update the L&F on the EDT, to prevent racing-condition issues.

It should be noted that the demo resets the L&F after updating the figure, otherwise any new figure or window would open using the newly-selected L&F. This is done in the updateInterface function as follows:

function updateInterface( lookandfeel )
 
    % Preserve the original L&F, before updating
    originalLnF = javax.swing.UIManager.getLookAndFeel;
 
    % Update the L&F in the demo figure as requested
    ... (all the existing code within the function)
 
    % Restore the original L&F for any new figure/window
    javax.swing.UIManager.setLookAndFeel(originalLnF);
 
end  % updateInterface

Note that after changing the L&Fs several times, some L&F properties night get “mixed-up” causing odd-looking L&Fs. The simplest solution in this case is to restart Matlab…

Matlab open training day (Israel) - click for details

Matlab open training day (Israel) - click for details

Readers in Israel are invited to attend a free training seminar that I will present on advanced Matlab topics in Herzliya, on Thursday April 4, 2013. The seminar is free, but requires registration. Additional details here. I will speak in Hebrew, but the presentation will be in English and I will be happy to answer questions in English.

]]>
https://undocumentedmatlab.com/blog/jtattoo-look-and-feel-demo/feed 13
Multi-line uitable column headershttps://undocumentedmatlab.com/blog/multi-line-uitable-column-headers https://undocumentedmatlab.com/blog/multi-line-uitable-column-headers#comments Wed, 27 Jun 2012 22:54:40 +0000 http://undocumentedmatlab.com/?p=2976
 
Related posts:
  1. Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
  2. Rich-contents log panel Matlab listboxes and editboxes can be used to display rich-contents HTML-formatted strings, which is ideal for log panels. ...
  3. Aligning uicontrol contents Matlab uicontrols can often be customized using plain HTML/CSS, without need for advanced Java. ...
  4. Displaying animated GIFs It is possible to easily display animated images in Matlab figure windows. ...
 
]]>
I often need to present data in tabular format in Matlab GUI, and this data often has relatively long column headers such as “Maximal draw/gain” or “Coefficient of elasticity”. When the table has many columns, these long column headers do not fit in the small space that is available:

uitable('data',magic(2),'ColumnName',{'Maximal draw/gain','Coefficient of elasticity'})

Default uitable behavior with long headers

Default uitable behavior with long headers

Creating multi-line headers

It makes sense to split such long column headers into a multi-line string. In the new (R2008a+) uitable, this can easily be done by adding the | character wherever we wish the line to be split; in both the new and the old uitable, we can also use the built-in HTML support by adding a simple <br/>. The following code snippet demonstrates both of these alternatives:

uitable('data',magic(2), 'ColumnName',{'Maximal|draw/gain', '<html><center />Coefficient<br />of elasticity</html>'});

Multi-line uitable headers

Multi-line uitable headers

Much more readable and useful, I think. Note that HTML code is left-aligned by default, so to center the header I added the <center> tag in the snippet.

If the text appears too crowded in the header cells, we can slightly reduce the header font, to make it appear more spaced-out. The following snippet illustrates this for the old uitable (available since Matlab 7.0 all the way until today), which can only use the HTML alternative since it does not support |:

headers = {'<html>Maximal<br />draw/gain</html>', ...
           '<html><center /><font size=-2>Coefficient<br />of elasticity</font></html>'};
uitable('v0','data',magic(2),'ColumnNames',headers);

Multi-line headers in the old uitable

Multi-line headers in the old uitable

Dynamic multi-line headers

While adding | or <br/> solves the problem for the majority of cases, it is sometimes difficult to know in advance where to place the line-split. This often happens when the column headers are dynamically generated by the program. If we omit the <br/> from our header strings, we get sub-optimal rendering: The new uitable simply hides all overflow terms, and the old uitable pushes them to the bottom:

headers = {'<html>Maximal draw/gain</html>', ...
           '<html><center /><font size=-2>Coefficient of elasticity</font></html>'};
uitable('v0','data',magic(2),'ColumnNames',headers);

Default dynamic HTML multi-line (old uitable)

Default dynamic HTML multi-line (old uitable)

I’ve tried numerous things, including CSS wrapping directives etc. None seem to work (I’ll be happy to hear a new idea that does work), except for the following weird-sounding trick: add a “<br/>&nbsp;” at the end of the HTML header string. If the column is wide enough, then this will be disregarded; otherwise, it will automatically split the string nicely:

headers = {'<html>Maximal draw/gain<br />&nbsp;</html>', ...
           '<html><center /><font size=-2>Coefficient of elasticity<br />&nbsp;</font></html>'};
uitable('v0','data',magic(2),'ColumnNames',headers);

Nicely-behaved dynamic HTML multi-lines

Nicely-behaved dynamic HTML multi-lines

Note: the &nbsp; part is important – the trick will NOT work without it!

Controlling the headers

HTML provides some degree of control over the table header row. Some additional aspects can be configured by accessing the underlying Java’s TableHeader sub-component. But here’s another trick that I found handy: I hide the table header row altogether, and use the top table data row for my headers. I can control this row’s height using JTable’s standard setRowHeight() method. Using some fancy cell background colors I can make this row stand out, and I can easily control other aspects as well.

The same trick can also be used for the row-header column: I can dispense with the standard one and use the table’s first column as a row-header column.

For more information on uitable customization, refer to section 4.1 of my Matlab-Java book, or to my uitable customization report.

Do you have a favorite trick with multi-line strings in Matlab GUI? If so, please share it in a comment below.

]]>
https://undocumentedmatlab.com/blog/multi-line-uitable-column-headers/feed 19