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

Customizing Matlab uipanels

Posted By Yair Altman On February 25, 2015 | 14 Comments

The major innovation in Matlab release R2014b was the introduction of the new handle-based graphics system (HG2 [1]). 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 [2] and in my Matlab-Java book [3]).
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 [4]).
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 [5] 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 [6] that we can use. I’ve already demonstrated [7] 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 [8], 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 [9] 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 [10] 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 [11], or via the BorderFactory [12] class. For example, let’s create a dashed border [13] 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.

Categories: GUI, Hidden property, Icons, Java, Medium risk of breaking in future versions, Stock Matlab function, UI controls


14 Comments (Open | Close)

14 Comments To "Customizing Matlab uipanels"

#1 Comment By Julian On February 26, 2015 @ 10:03

Thanks for your great blog.

Trying it out for fun All this Java / GUI stuff is not very familiar to me..) I did get an error with

jPanel.getBorder.setBorder(jNewBorder)

but

jPanel.setBorder(jNewBorder)

was OK

#2 Comment By Yair Altman On February 26, 2015 @ 10:10

@Julian – please state your exact code snippet and the error you received – it should have worked without any error.

#3 Comment By julien On February 26, 2015 @ 15:04

Thanks Yair for this very interesting post… It is indeed a very good news! More than its aspect (borders, titles), it is finally a “real” java container in which we will be able to use java layout managers and which will naturally clip its components. It was time!
I am sorry but I do not have the R2014B yet… I was wondering if you had prospected axes objects. Are they now JComponents like uipanels or are they still draws at the canvas level?

#4 Comment By Yair Altman On February 26, 2015 @ 16:19

@Julien – HG2 graphics are still drawn at the canvas-level. The canvas itself has changed: it is now a com.mathworks.hg.peer.JavaSceneServerGLJPanel object, which is a MathWorks extension of the standard [20] panel when the figure renderer is OpenGL, and com.mathworks.hg.peer.JavaSceneServerPanel when the renderer is Painters.

In 14b, ZBuffer is no longer a documented figure renderer option (you don’t see it when you run set(gcf,'Renderer')). However, it is still an accepted renderer value, and apparently revert to the OpenGL renderer, resulting in a GLJPanel. This was probably done by MathWorks for backward compatibility with existing code which might deliberately request a ZBuffer renderer.

#5 Comment By Julien On February 27, 2015 @ 14:56

Thanks… I was dreaming to a world where axes would have their own containers so that they could be added to any Java container, or could be scrolled.
So, there are still 2 overlayed content panes, one for uicontrols and uipanels and another for graphics (actually 2, depending on renderer). Do you have an idea of the reason why graphics is drawn like this at the canvas level ?

#6 Comment By Yair Altman On February 28, 2015 @ 09:49

@Julien – I assume this is done for performance reasons, graphics being drawn by native C code. However I don’t know this for a fact.

#7 Comment By Tom On March 5, 2015 @ 09:09

I have found that GUIDE graphics are impossibly broken in 2014b. In the guide designer, controls disappear and cannot be made to reappear only with great effort and luck. In addition, controls with normalized units sometimes have their position values reset to all zeros or to 0 and 1.

The only workaround I have gotten from Mathworks is to convert to a programmatic interface.

#8 Comment By Yair Altman On March 5, 2015 @ 09:42

@Tom – …or to hire a professional Matlab expert to do it for you… 🙂

#9 Comment By Stan On April 28, 2015 @ 08:11

I have experienced the same problem with position values getting reset for controls within panels. I believe that this does not happen if the figure is changed to be non-resizable.

#10 Comment By lsh On November 4, 2015 @ 01:28

Hi Yair,

I found that when I invoke jpanel.JavaFrame.getPrintableComponent in my script, it will return something like this:
com.mathworks.hg.peer.ui.UIPanelPeer$UIPanelJPanel[,0,0,0x0,invalid,layout=...]

However when I invoke this in the command window, it will return normal value:
com.mathworks.hg.peer.ui.UIPanelPeer$UIPanelJPanel[,0,0,300x300,layout=...]

Why does this happen?
I was using MATLAB 2014b.

#11 Comment By Yair Altman On November 4, 2015 @ 01:54

@LSH – this is probably an [21]. Add a call to drawnow before requesting the PrintableComponent.

#12 Comment By Mhyd On December 7, 2015 @ 10:26

Hi Yair,

Thanks for sharing this info.
I was wondering how would one potentially remember these commands :

jNewBorder = javax.swing.border.LineBorder(jColor, 1, true);  % red, 1px, rounded=true
jPanel.getBorder.setBorder(jNewBorder);

as in how would one know to look specifically into javax.swing.border.LineBorder to create the new java border..
seems a long name to commit to memory

#13 Comment By Yair Altman On December 7, 2015 @ 14:30

@Mhyd – simple: Google “java border” and the very first search result is Java’s official tutorial on [22], and this includes a short discussion of various predefined border styles, including LineBorder which is the simplest border.

#14 Comment By OrO On July 20, 2017 @ 04:56

It helps a lot. Thank you !
Does it work in MATLAB Compiler ? I do not see a reason why it should not but I would like to have your confirmation.


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

URL to article: https://undocumentedmatlab.com/articles/customizing-matlab-uipanels

URLs in this post:

[1] HG2: http://undocumentedmatlab.com/blog/hg2-update

[2] this blog: http://undocumentedmatlab.com/blog/tab-panels-uitab-and-relatives

[3] Matlab-Java book: http://undocumentedmatlab.com/books/matlab-java

[4] example: http://undocumentedmatlab.com/blog/button-customization

[5] javax.swing.JPanel: http://docs.oracle.com/javase/7/docs/api/javax/swing/JPanel.html

[6] wide range of alternative borders: http://docs.oracle.com/javase/tutorial/uiswing/components/border.html

[7] demonstrated: http://undocumentedmatlab.com/blog/customizing-uicontrol-border

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

[9] LineBorder: http://docs.oracle.com/javase/7/docs/api/javax/swing/border/LineBorder.html

[10] MatteBorder: http://docs.oracle.com/javase/7/docs/api/javax/swing/border/MatteBorder.html

[11] Border interface: http://docs.oracle.com/javase/7/docs/api/javax/swing/border/Border.html

[12] BorderFactory: http://docs.oracle.com/javase/7/docs/api/javax/swing/BorderFactory.html

[13] dashed border: http://docs.oracle.com/javase/7/docs/api/javax/swing/BorderFactory.html#createDashedBorder(java.awt.Paint,%20float,%20float,%20float,%20boolean)

[14] Customizing uicontrol border : https://undocumentedmatlab.com/articles/customizing-uicontrol-border

[15] Customizing Matlab labels : https://undocumentedmatlab.com/articles/customizing-matlab-labels

[16] Transparent uipanels : https://undocumentedmatlab.com/articles/transparent-uipanels

[17] Customizing editboxes : https://undocumentedmatlab.com/articles/customizing-editboxes

[18] Customizing Matlab's Workspace table : https://undocumentedmatlab.com/articles/customizing-matlabs-workspace-table

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

[20] : https://jogamp.org/deployment/v2.1.2/javadoc/jogl/javadoc/javax/media/opengl/awt/GLJPanel.html

[21] : https://undocumentedmatlab.com/blog/matlab-and-the-event-dispatch-thread-edt

[22] : https://docs.oracle.com/javase/tutorial/uiswing/components/border.html

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