Button customization

Matlab’s button uicontrols (pushbutton and togglebutton) are basically wrappers for a Java Swing JButton object.

This will be the first in a series of posts showing how Matlab uicontrols can be customized in ways that you may never have thought possible.

Probably the simplest undocumented customization is the control’s acceptance of HTML and CSS Strings:

tooltip = '<html>HTML-aware<br><b>tooltips</b><br><i>supported';
labelTop= '<HTML><center><FONT color="red">Hello</Font> <b>world</b>';
labelBot=['<div style="font-family:impact;color:green"><i>What a</i>'...
          ' <Font color="blue" face="Comic Sans MS">nice day!'];
set(hButton, 'tooltip',tooltip, 'string',[labelTop '<br>' labelBot]);

Button with HTML label and tooltip

Button with HTML label and tooltip

For more powerful customization, we need to access the control’s underlying JList object. We do this by using my FindJObj submission on the File Exchange (which was explained here):

>> jButton = java(findjobj(hButton))
jButton =
com.mathworks.hg.peer.PushButtonPeer$1[,0,0,...]

Now that we have the jButton Java object reference, we can use get and set just like any Matlab handle. To see the list of all available properties, methods and callbacks, we can use my UIINSPECT submission on the File Exchange, or use Matlab’s built-in methodsview function.

This post is too short to present all the numerous ways in which the control can be customized with the Java properties and methods. Let’s list some of the more interesting properties:

  • Border – specified the border frame around the button, which is responsible for its 3D appearance. It can be modified to anything from a simple colored borderline to a recurring icon-pattern, as shown here. If set to [] then the button achieves a flat appearance, which can be useful for displaying click-able labels. For example, the blog hyperlink at the bottom of the FindJObj window is a simple button with no border, an HTML label and a callback that opens this blog webpage using the built-in web function:
    Button appearing as a hyperlink label

    Button appearing as a hyperlink label

  • Cursor – this can be used to set a control-specific cursor. For example, in the hyperlink button above, the cursor was set to: java.awt.Cursor(java.awt.Cursor.HAND_CURSOR). In another post I’ll show how to set a custom cursor, like the following Matlab icon:
    Custom cursor

    Custom cursor

    Note: This feature only works on R2013a and earlier; custom cursors are ignored in Matlab R2013b and newer (see here).

  • DisplayedMnemonicIndex – (default=-1) indicates the character position within the text label where the Mnemonic (i.e, keyboard shortcut) should be displayed. Associated property Mnemonic (default=0) indicates the ASCII code of the mnemonic. In the following case, DisplayedMnemonicIndex=3 (remember that Java indices start at 0) and Mnemonic=73 (=’r’):
    Button With mnemonic

    Button With mnemonic

  • Margin, VerticalAlignment, HorizontalAlignment – these properties enable setting the label contents with respect to its borders. For example:
    Top-left with 8-pixel top margin

    Top-left with 8-pixel top margin

  • Icon, DisabledIcon, DisabledSelectedIcon, PressedIcon, RolloverIcon, RolloverSelectedIcon, SelectedIcon – these icons may be set to present a different appearance depending on component state. Associated property IconTextGap (default=4) determines the gap in pixels between the icon and the button text label. Associated properties HorizontalTextPosition and VerticalTextPosition specify the label text’s alignment relative to the label icon. These two properties accept the same SwingConstants values as HorizontalAlignment and VerticalAlignment above. For example, let’s display an icon to the right and upward of the text:
    
    myIcon = fullfile(matlabroot,'/toolbox/matlab/icons/warning.gif');
    jButton.setIcon(javax.swing.ImageIcon(myIcon));
    jButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
    jButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
    

    Button with text and icon

    Button with text and icon

  • MultiClickThreshhold – (default=0) sets the number of milliseconds between subsequent processed user mouse clicks on the button. Any clicks that occur within the specified number (e.g., fast double-clicks) will be considered by the component as only a single click. The default value of 0 means that all clicks will be processed separately, which is often undesirable in GUI applications. Remember that the value is in milliseconds, not seconds.
  • FlyOverAppearance – boolean flag (default=false); if set, the button appearance is changed to a flat (2D) appearance with a special 3D border effect displayed on mouse hover. This appearance is useful for toolbar buttons, and is an extension by Matlab’s button implementation (does not exist in the standard Swing class).

There are quite a few other useful properties, methods (for example, jButton.doClick() to programmatically click a button) and even some 30 callbacks, detailed in a separate post. The list above is by no way comprehensive – I hope it whet your appetites for exploration using FindJObj and UIINSPECT – it’s a fun ride and the GUI rewards are worth the effort!

Please let me know of any nice customizations in your Matlab applications. Leave a comment below or drop me an email.

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

Tags: , , ,

Bookmark and SharePrint Print

30 Responses to Button customization

  1. Pingback: Undocumented MATLAB Tips by Yair Altman | blinkdagger

  2. neurostu says:

    I’m having some problems with setting an ImageIcon on the buttons, here is my code:
    http://pastebin.com/f1e4b6086

    I create a jButton object for each of the three uicontrol buttons I create but whenever I set the icon on one of the three buttons it always sets it to the first of the three.

    I’m running matlab 2008b

  3. Peter Steinberg says:

    This is all very useful. Thanks! One question: do you know how to underline text in a static text element?

    • @Peter – I assume you meant the uicontrol text control, not the axis-based label generated by text (for this you can use tex-formatting).

      For text uicontrol customizations, read here.

  4. Karthik S says:

    These are excellent tips on customization! How do I automatically resize an icon in the button?

    • @Karthik, you can place a listener on the button’s Position property and in its callback you could resize the button’s contents.

    • Karthik S says:

      Thank Yair. The button is on a GUI. I wanted the image on the button to resize when I resize the GUI. The button resizes automatically with the GUI, but, when I place a listener like you suggested, the callback isnt being executed.

    • @Karthik – simply use your figure’s ResizeFcn property in order to catch GUI resize events

    • Karthik S says:

      I’m using the auto Resize option on the main GUI, so I dont think I have explicit control of the GUI’s resizefcn

    • @Karthik – of course you do: every Matlab figure has the ResizeFcn property. It doesn’t matter how you resize the figure, this callback will get invoked.

  5. vanilou says:

    Hi ! I would like to do a round pushbutton, is that possible in matlab ?

  6. Raphael says:

    thanks a lot for these tips Yair !

    I was working on adding icons to GUI buttons today and ran into 2 troubles:
    – the javax.swing.ImageIcon seems to keep the image in memory. In case of a second execution with the same file path, it would use the copy in memory and not the newer version. Is there a way to force the reloading of the file ?
    – Once an icon is used in a gui, none of the properties for the text alignment work anymore. Left, Right, Center: everything is centered and the gui parameters are unresponsive.

    Did I forgot something or is that a bug that you’re aware of ?

    thanks
    Raphael

    • @Raphael – ImageIcon caches files so it will not reload the same image twice. There are alternatives (example) that you can use instead of ImageIcon. This is really a pure Java question for which you should search on pure Java forums.

      Regarding alignment, you can use the HorizontalAlinment(), HorizontalTextPosition() methods (and similarly for Vertical*) of the JButton reference. It’s covered in detail in Section 6.1 of my Matlab-Java programming book.

  7. Aaron says:

    Hello, Yair.

    I’ve frequented your site a lot in the last few months as I’ve gotten into GUI programming in MATLAB. I recently ran into a little problem that I’m trying to work out.

    I am trying to create a GUI button with one line of text that is partially left-aligned and partially right-aligned. I was hoping to use CSS within the string field as such:

    h = uicontrol('Style','PushButton','Position',[20 20 150 40]);
    set(h,'String','<html><p style="float: left;">Left Text</p><p style="float: right;">Right Text</p></html>');
    % I know the closing tags are not necessary

    However, this creates two separate lines (which are both centered in the push button) despite the float command.

    Is it possible to do this at all using HTML/CSS? Or is a JAVA solution needed or, even still, possible?

    • Yair Altman says:

      @Aaron – Unfortunately, Java Swing’s support for CSS is not complete. I posted a similar question on StackOverflow back in 2011 when I saw that <div> splits the text into two lines instead of continuing on the same line. The solution in that case was to use <span> rather than <div>. It might work for your case as well.

  8. Pingback: Undocumented button highlighting | Undocumented Matlab

  9. Darin says:

    Hi Yair,

    Thanks, this info is very helpful! (Even 3+ years later :)) When I used the code on a pushbutton, it centered the icon… and had the text centered as well. I tried using the IconTextGap property but to no avail. How do you keep the text on the right and the icon on the left? (instead of both icon and text centered?)

    Here’s my code…

     S.sharedyaxis = uicontrol('style','push',...
        'units','pix',...
        'HorizontalAlign','left',...
        'string','SYA', ...
        'fontsize',12,'fontweight','bold');
     
    jshared = findjobj(S.sharedyaxis,'nomenu');
    icon = javax.swing.ImageIcon('C:\SYA_turnon.gif');
    y = java(jshared);
    y.setIcon(icon);
  10. Chris says:

    Hi Yair,

    thanks for all the great help! I read your instruction of changing the border of a button, but it did’nt work. I want to create a button in a matlab gui with an image as ‘CData’. The buttons position should change with the figure’s position. But the image should not be resized (it is a small image with only few pixels). When resizing the figure, the border of the button becomes visible. To avoid that, I tried to create a borderless button and unfortunately that did’nt work. Here’s my code

    button = uicontrol('Style','pushbutton','String','Hello');
    jbutton = findjobj(button);
    jbutton.border = [];

    What am I doing wrong?

    Best
    Chris

    • Yair Altman says:

      @Chris – I’m not sure what happened in your case but why use a button control at all? you can use an invisible axes, similar to my “buttons” in this utility.

    • Chris says:

      Wow, thanks for the link. Looks great!
      I am using a button because I want it to have a tooltip. Is it possible to generate a tooltip for an axes object? I tried with your function findjobj, but I didn’t manage it.
      Regards
      Chris

    • @Chris – axes are not Java objects, so you cannot use findjobj with them. And no, they don’t have tooltips.

    • Chris says:

      OK, thanks.

  11. Cristiano says:

    Hello, Yair.
    The methods you mention is useful,however,when I zoomed the window I found the Icon was overlapped by the String. Finally,If I let a dialog or form have a FIXED size,the problem is solved. I intended to resize dialogs or forms in the Windows without overlapping the Icon, but I didn’t handle it.

    info_icon_path = fullfile('C:\Users\Zhang\Desktop\icons\ModelAdvisor.png');
    info_aSi = uicontrol('Style','PushButton',...   
                     'position',[10,10,120,70],...
                     'TooltipString','',...  
                     'fontsize',10,...      
                     'fontweight','bold',...      
                     'String','Description',...
                     'Enable','on');
     
    jButton_info_nFS = findjobj(info_aSi);              %find Java-Handle of Button
    jButton_info_nFS.setIcon(javax.swing.ImageIcon(info_icon_path));    %add image to button
    set(jButton_info_nFS,'HorizontalTextPosition',javax.swing.SwingConstants.RIGHT);    %align text
    set(jButton_info_nFS,'VerticalTextPosition',javax.swing.SwingConstants.CENTER);
  12. Brian says:

    Hello Yair,
    Thanks for all your work on this site.

    I’ve had a heck of a time trying to figure out how to do a border-less button. I tried using both the null vector ‘[]’ approach and by setting the border directly by using the methods from the border factory class from the link you posted above (see below). However none of these attempts result in a border-less button.

    I followed your example of a borderless button from here:
    https://undocumentedmatlab.com/blog/borderless-button-used-for-plot-properties

    I just can’t understand why this won’t work here in this simplified example. My simple code looks like this so far:

    f=figure('Menubar','none', 'Position',[200 200 300 200]);
    p=uipanel(f, 'BackgroundColor', [0 0 1]);
    h = uicontrol('parent', p, 'Style','pushbutton', 'String','click', ...
       'Units','normalized', 'Position',[0.3 0.3 0.5 0.5],'BackgroundColor', [0 0 1]);
    jh = findjobj(h);
    jh.setBorder(javax.swing.BorderFactory.createEmptyBorder()); %attempt 1 does not remove border
    jh.border=[];                                                %attempt 2 does not remove border
    jh.setBorder([]);                                            %attempt 3 does not remove border
    jh.border=javax.swing.BorderFactory.createEmptyBorder();     %attempt 4 does not remove border

    I’m using MATLAB 2015a and Windows7. Any way you can provide a simple complete code for a border-less button or edit above?

    Thank You!

  13. David says:

    Hi Yair,
    First of all thanks for this great site.
    I have a problem when resizing the button parent window, the icon image dissappears.

    f = figure;
    b = uicontrol(f);
    jButton = java(findjobj(b))
    jButton.setIcon(javax.swing.ImageIcon(iconPath))

    I am using R2015a and Windows7

    • @David – you can place the relevant setIcon() code in a small function and set the parent’s SizeChangedFcn callback to this function’s handle. This way whenever the parent resizes the icon will get repainted. Add a call to jButton.repaint() after setIcon(), to ensure that it actually gets repainted.

Leave a Reply

Your email address will not be published. Required fields are marked *