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]);
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:
- 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:
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’):
- Margin, VerticalAlignment, HorizontalAlignment – these properties enable setting the label contents with respect to its borders. For example:
- 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);
- 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.
[…] covered. I find the contrast quite refreshing. For instance, in Yair’s most recent post on Button Customization, he discusses the intricacies of what one can accomplish with a simple push button. So if […]
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
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.
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.
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
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.
Hi ! I would like to do a round pushbutton, is that possible in matlab ?
Not easily. The simplest way would be to draw a rounded patch that looks like a button on an invisible axes and then monitor click events on this patch.
Ok, thank you !
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 ofImageIcon
. 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.
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:
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?
@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.[…] 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 […]
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…
@Darin –
This is covered both in my book and my uicontrols customization report.
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
What am I doing wrong?
Best
Chris
@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.
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.
OK, thanks.
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.
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:
http://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:
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!
@Brian –
Yair, the following didn’t work for me either:
jh.setBorderPainted(false);
Regards,
Kim
Hi Yair,
First of all thanks for this great site.
I have a problem when resizing the button parent window, the icon image dissappears.
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 tojButton.repaint()
aftersetIcon()
, to ensure that it actually gets repainted.So, I’m having trouble finding information on this.
If I change the border of a button, then change the background color, the border resets. Then I am not able to change the border whatsoever. Is there a way I can change the border and the background? I do not want to be stuck using borderless buttons if I don’t have to
Thanks
The default Java Look&Feel for UI buttons paints the border together with the contents, and apparently prevents changing both of them together (reference). Changing to a different Look&Feel might possibly help, and of course you could always create and use a custom Java class that inherits
JButton
. In any case, this is a pure Java Swing issue (not Matlab) so you should search for answers in Java forums.Cross-reference: http://undocumentedmatlab.com/articles/customizing-uicontrol-border