A couple of days ago, a reader of this blog posted a comment, asking whether it is possible to change Matlab’s Desktop color scheme, and its general UI look. Instead of providing a short answer, I will use the opportunity to answer in a full article. So this is for you, Egon 🙂
Matlab’s underlying Look-and-Feel
One of Matlab’s great advantages is cross-platform compatibility. Generally speaking, Matlab applications written on Windows will work as-is on Macintosh and Linux.
Java has similar cross-platform compatibilities, but enables much greater control over the look-and-feel (L&F or PLAF) of application GUI. In a nutshell, L&Fs affect the appearance and behavior of menus, controls, color schemes etc., using a properties plug-in architecture. Java programmers can choose to use either a platform-independent L&F (called the Metal L&F), or a platform-specific L&F. The benefit of using Metal is that the application looks essentially the same on all Java-supported platforms; the drawback is that they do not look like native applications on any platform…
Matlab, whose GUI is based on Java (not surprising to readers of this website), has chosen to use a platform-specific L&F on each of the platforms on which it is supported. So, Matlab on Windows looks like a native Windows application, whereas on Macs it looks similar to Mac apps (notwithstanding the well-known X11 migration issues). Of course, this means that Windows Matlab looks and behaves differently from Mac/Linux Matlabs. Note that the differences only affect the Desktop, tools/utilities (Editor etc.) and the general L&F – it does not affect the displayed plots. In practice, the differences are visible but easily understandable.
Changing the L&F
We can get the list of available L&Fs on our system as follows (below is the list on my Windows system):
>> lafs = javax.swing.UIManager.getInstalledLookAndFeels lafs = javax.swing.UIManager$LookAndFeelInfo[]: [javax.swing.UIManager$LookAndFeelInfo] [javax.swing.UIManager$LookAndFeelInfo] [javax.swing.UIManager$LookAndFeelInfo] [javax.swing.UIManager$LookAndFeelInfo] [javax.swing.UIManager$LookAndFeelInfo] >> for lafIdx = 1:length(lafs), disp(lafs(lafIdx)); end javax.swing.UIManager$LookAndFeelInfo[Metal javax.swing.plaf.metal.MetalLookAndFeel] javax.swing.UIManager$LookAndFeelInfo[Nimbus com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel] javax.swing.UIManager$LookAndFeelInfo[CDE/Motif com.sun.java.swing.plaf.motif.MotifLookAndFeel] javax.swing.UIManager$LookAndFeelInfo[Windows com.sun.java.swing.plaf.windows.WindowsLookAndFeel] javax.swing.UIManager$LookAndFeelInfo[Windows Classic com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel] |
We can change the L&F to any of the installed L&Fs, as follows:
javax.swing.UIManager.setLookAndFeel('javax.swing.plaf.metal.MetalLookAndFeel'); |
Although not listed in the installed L&Fs, Matlab also enables access to a 3rd-party L&F called Plastic3D by www.jgoodies.com. Plastic3D L&F generates slick stylish GUI:
javax.swing.UIManager.setLookAndFeel('com.jgoodies.looks.plastic.Plastic3DLookAndFeel') |
The JIDE class library by www.jidesoft.com, which is bundled with Matlab, and specifically its jide-common.jar file, contains a separate set of 3rd-party L&Fs: Aqua, Eclipse (Metal & Windows variants), Office2003, VSNet (Metal & Windows variants) and Xerto. Unfortunately, in Matlab releases starting around 2009, JIDE stopped including full L&F classes in jide-common.jar, and started using L&F extensions using their com.jidesoft.plaf.LookAndFeelFactory class. I have not been able to use this class properly, but readers are welcome to try (please tell me if you succeed).
External L&Fs can also be downloaded and then used in Matlab. For example: Alloy, Synthetica and many others.
The current and standard L&Fs can be retrieved by using the respective static methods javax.swing.UIManager.getLookAndFeel() and getSystemLookAndFeelClassName().
Matlab also has a utility class com.mathworks.mwswing.plaf.PlafUtils that contains static methods that query the current L&F: isPlasticLookAndFeel(), isAquaLookAndFeel(), isMetalLookAndFeel(), isMotifLookAndFeel() and isWindowsLookAndFeel(). For some reason there is no method for the new (R2010a+) Nimbus L&F.
Nimbus L&F offers great potential for a cross-platform vectorized appearance, the ability to customize/skin pretty much every aspect of the visual appearance and component behavior, replacing Swing’s Synth L&F which was used for such customizations in earlier Matlab/Java releases. Nimbus is pre-installed as a non-default L&F in Matlab R2010a (7.10) onward, because it seems that most designers who target a single platform still prefer the native L&F.
Component-specific L&F
You can also modify the L&F of specific components, not just the entire Matlab. To do this, simply modify the L&F immediately before creating your GUI component, and restore the original L&F afterward (note how you can use either the L&F class name or its class reference):
% Update the current L&F originalLnF = javax.swing.UIManager.getLookAndFeel; %class newLnF = 'javax.swing.plaf.metal.MetalLookAndFeel'; %string javax.swing.UIManager.setLookAndFeel(newLnF); % Create GUI using the modified L&F hFig = figure(...); hComponent = uicontrol(...); jComponent = javacomponent(...); % Ensure that the controls are fully-rendered before restoring the L&F drawnow; pause(0.05); % Restore the original L&F javax.swing.UIManager.setLookAndFeel(originalLnF); |
Components can update their L&F to the current L&F using their jComponent.updateUI() method. Components that are not specifically updated by invoking their updateUI() method will retain their existing (original) L&F – the L&F which was active when the components were created or last updated.
Fine-grained L&F property control
The default settings for the L&F can be retrieved using the static method javax.swing.UIManager.getDefaults(), which returns an enumeration of the thousand or so default settings:
>> defaults = javax.swing.UIManager.getDefaults; >> propValues = defaults.elements; propKeys = defaults.keys; >> while propKeys.hasMoreElements key = propKeys.nextElement; value = propValues.nextElement; disp([char(key) ' = ' evalc('disp(value)')]); end com.sun.java.swing.plaf.windows.WindowsLabelUI = class com.sun.java.swing.plaf.windows.WindowsLabelUI ... (~1000 other property settings) SplitPane.dividerSize = 5 DockableFrameTitlePane.stopAutohideIcon = javax.swing.ImageIcon@1f4e4c0 FormattedTextField.caretBlinkRate = 500 Table.gridColor = javax.swing.plaf.ColorUIResource[r=128,g=128,b=128] |
Specific settings can be modified by using javax.swing.UIManager.put(key,newValue).
Have you found any useful L&F or property that you are using in your application? If so, please share them in the comments section below.
In a single word: “wow!”. Thank you very much, this helps me forward a lot, as I’m trying to get MATLAB to look a bit like a GTK application on Linux.
But unfortunately MATLAB throws a lot of errors when changing the LAF (from the default Plastic3D to GTK+ or anything else for that matter). Some parts of the desktop actually change a bit; other parts just stay the same (looking a bit like the Frankenstein monster). When I find a solution for this, I will surely let you know.
Egon
Changing the L&F does cause problems with Java exceptions being thrown. To change the entire desktop, set the L&F then invoke
The problem with changing the L&F may relate to missing extensions or defaults added by MATLAB at start up. For the JIDE classes that Yair mentions you need to invoke
after setting the L&F.
This is very cool. Plastic3d looks great, but nimbus gives me all kinds of exceptions whenever i click something and makes the matlab desktop completely unusable. But it seems to work with my GUI… though it has some transparency issues with the buttons so I think i’ll avoid it altogether for now… hopefully it gets better support in the future. If anyone gets it fully working i’d love to hear about it.
For changing the l&f of a single component… if I do:
I get metal for the jbutton and my default l&f for the uicontrol button, which i’m guessing is how it’s supposed to work (as opposed to metal for both). But if i run just the first 3 lines, it screws up my matlab desktop too… is the trick to change it back to the default before calling drawnow?
@Matt – the issue you see with the uicontrol button is simply due to the fact that the button has not completed its onscreen rendering before the originalLnF has been returned (see my EDT article).
To fix this, simply place a drawnow command before you restore the originalLnF. You will then also be able to see what a Metal-based figure and menu-bar looks like.
Ah, thanks, I see how that works now. But I’m still confused about when using javax.swing.UIManager.setLookAndFeel affects the matlab desktop and when it only affects an individual figure. I was expecting to see the desktop flash to metal when drawnow was called, then flash back to the default. Based on the behavior described above I’m inferring that drawnow only affects figure windows and not the main desktop, which doesnt quickly flash to metal because setLookAndFeel() is called again to switch it back to the default look and feel before it gets a chance to update its appearance. Does that sound correct?
@Matt – yes, that is correct. To force a repaint of the main desktop, you can do the following (based on Malcolm’s comment above):
I can’t import third party L&F in matlab ! it keeps telling me the same error when trying to set another L&F other than the few default ones installed , anybody can help ?
@Sherif – try to add the L&F class/JAR files to your static Java classpath (edit classpath.txt), then restart Matlab and retest
thx Yair 🙂 it worked , but is there another way to change the L&F in runtime and build a GUI and then restore the default L&F ?
it didn’t work when i added the JAR files to the dynamic classpath !
i want to add the files to the dynamic classpath bec. i want to add them by code automatically in the beginning of the m file not manually by the user !
@Sherif – Matlab’s dynamic Java classpath is known to cause problems in all sorts of Java-related aspects. You can try using the dynamic classpath, but if you encounter errors your best choice is to update the static classpath. You can add Matlab code that does this automatically (better ask for user confirmation before you do this, of course)
thx again 🙂 .. now it works well ..
but again as usual another problem , what about standalone compilation ?!
i couldn’t even run the compiled file :S
any ideas ?!
Thanks a lot again 🙂
@Sherif – I suggest a two-step debugging process:
1. Remove the L&F code from your code and check that it now runs properly – if not then your problem probably lies elsewhere
2. Add the L&F JARs to the compiler’s external files section
– Yair
Hi, thanks for very interesting article !
But is there any solution if I would like to execute Matlab with desired LAF from console ?
Something like on passing parameter swing.defaultlaf=bla.bla.bla to the Java machine that runs Matlab GUI ?
@Dmitry – yes – the commands mentioned in the first section of this article can be executed from the Matlab Command Prompt (console).
-Yair
Yair, Thank for reply, but it seems I asked it not entirely correct 🙂
I meant how could I start matlab from Linux console with desired predefined LAF ?
Like standalone Java application can be started with different LAF when you execute it as
java -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel App
I’m not sure that it’s possible at all, because it seems matlab uses some native executor utility for starting.
@Dima – as far as I know you cannot pass JVM startup options in the Matlab command line
– Yair
Hi Yair.
I am trying to make my existing Matlab GUI real pretty.
I am currently experimenting with the LAFs, which is a great improvement, especially since I am using the old uitable. However, as mattdash commented above, the uicontrols do not use the applied LAF. Some of the colors are changed, but, for example, if I compare the uitable scrollbar to the uicontrol scrollbar under the Metal LAF, then the uicontrol scrollbar does not look as nice with the gradient color. Is there any way of making the standard Matlab uicontrols use the new LAF?
@Tal – read my reply to Matt’s comment above, particularly the part about using drawnow
-Yair
Yair, my situation is not the same, as I never modify the LAF back. I keep it on metal.
I tried the following:
The jComponent is really nice with the gradient coloring. The Matlab uicontrol looks plain gray. However, while pressed it does change its color to blue, like the jComponent. So, I get some kind of hybrid behavior. Is there any way around it without converting all of my uicontrols to javacomponents?
Tal.
@Tal – This was an interesting question. I almost gave up…
Aparently, Matlab uses the non-PLAF-compliant java.awt.Color for its uicontrols’ Background property, rather the more standard PLAF-compliant javax.swing.plaf.ColorUIResource.
To fix this directly on the uicontrol, use my FindJObj utility as follows:
BTW, the same happens with the Font property, which uses java.awt.Font rather than javax.swing.plaf.FontUIResource.
-Yair
Yair,
Many thanks for the educated answer.
I guess i will create a function that converts all UI colors to plaf colors.
I still have two related questions:
1. The findjobj() utility (which is wonderful, btw) returns an empty result when I use it as follows:
However, if I use it to hunt objects containing specific attributes, such as:
It returns exactly the handle I want.
However, searching for a handle according to the string attribute is not very robust.
Is it possible to use the Tag attribute to do so (I tried ‘Tag’ and ‘Name’, which did not work), or another “unique” attribute?
2. I used the PLAF to modify the appearance of a uitable (I am using your createTable() on Matlab 7.04), which works great, except for the header.
I tried, for example:
But the table header is left gray.
However,
Does change the table background.
So, what am I doing wrong here.
Many thanks again,
Tal.
@Tal –
1. Perhaps you forgot to add a drawnow before findjobj? If the control is not fully rendered when you run findjobj, no wonder you get []. Alternately, you can use the ‘class’ property.
2. I don’t know which property (if any) affects the table header. You can also try to use HTML and CSS backgrounds. I’ll show an example of this in tomorrow’s post
-Yair
Yair,
Thanks again for your comments and replies.
Regarding the drawnow() – this was not the problem, it is probably my Matlab version.
Anyway, I wrote a function that applies the PLAF colors to all uicontrols within a figure, using the class option of findjobj, as you suggested.
I was surprised to find out that in each class, one handle is not returned.
So, I debugged and I believe you have a bug:
Line 646 reads:
Where IMHO, it should read
So here – you got something back from me…
Many thanks (again)
Tal.
Well, Yair
Thanks to you, I am almost done with my UI.
The only uicontrol which still defies the PLAF is the slider uicontrol.
It takes the PLAF colors, but the color is flat not the pretty gradient coloring of the metal LAF.
Is there any way of forcing it to adhere to the PLAF, or should I replace it with a jscrollbar?
Tal.
@Tal – I always prefer to use JScrollBars rather than the standard slider uicontrol. JScrollBar not only looks visually more appealing than the Matlab slider uicontrol (which looks so Windows95 1990’s-style in my opinion), but also has a more consistent look-and-feel with other Matlab uicontrols, since they are all based more closely on Swing.
Not to mention the fact that it’s much easier to get to the underlying extra Java functionality (continuous slider callbacks, for example) with a plain-ol’ JScrollBar.
-Yair
Hi Yair,
I am new to all this stuff. Fantastic work!.
I know my problem is not completely relevant to the discussion going on here but this is what i want to do.
I am trying to customize matlab tollbar or simulink model window toolbar with my own icons but not able to do so.
Please can you help me with this.
Thanks
@Tarun – maybe this will help you: http://undocumentedmatlab.com/blog/figure-toolbar-customizations/
Hi Yair,
I actually wanted to add few icons in MATLAb main Frame window or Simulink Model Window not in Figure window.
Shortcut of certain application.
Is there any way to do this?
@Tarun – you can add a toolbar shortcut as described here
Hey, thanks for this article, it was a great help!! MATLAB’s background color not being the same as the rest of my desktop really irked me, and I had to fix it. Changing the theme to the system look and feel (GTK for me) didn’t work out well, as a lot of exceptions started being thrown, and the desktop didn’t get repainted properly, with lots of glitches and artifacts, so what I did was use the code in the “Fine grained L&F property control” section to scan for all properties that matched the background color I didn’t want, then change them to the background color I wanted. It worked!
The problem now is that these settings don’t get saved after I close MATLAB. Are they supposed to be saved, or do I have to write a start-up script so that the changes get made every time I start MATLAB?
@ZOMGxuan – I’m afraid that you need to write a small start-up script that you can call from within your startup.m file so that it automatically gets executed whenever you start Matlab. It would be nice if you could post this script here in a comment. If it’s too large, you can email it to me and I’ll upload it to this website and post a link here.
The script isn’t very long, so I’ll just post it here.
Here, my old background color in (r,g,b) is (236, 233, 216), which is the default for the Metal look & feel (and Plastic3D as well, I think). My new background color is (237, 237, 237), which is the same background color that my GTK theme uses. Replace the colors as appropriate. To find out the default background color for a particular look & feel, I had to list out all the key value pairs of UI properties, and look for a color that kept repeating that matched the background color I was seeing (you can check using a color picker online or something). In general, this color should be the same as the value of the MenuBar.background property.
@ZOMGxuan – thanks. You might also consider adding the following items to your startup script:
Thanks! Oh, I forgot to mention that running the script causes a bunch of Java exceptions to be thrown, but it doesn’t seem to have any negative impact after that.
Hi Yair,
Thanks for the article. When i use findjobj command in GUI(designed with guide) uitabs not shown. I tried to handle GUI components in opening function but it returns empty array even i use pause or drawnow commands. When i put findjobj in another function it captures the handle but in this case uitabs are not shown. Is there any way to correct this?
Best Wishes,
@Alp – I do not have an immediate answer. Solving this will require looking at your application code. I will be happy to help you with this, for a fee to compensate me for my time and expertise. If you are interested, please contact me offline using the email link at the top-right of this page.
I’m trying to get a gui (figure window with uicontrols and uipanel; I’m turning off the toolbar and menubar for my figure window so I don’t need those) on an apple computers to look “plastic” (i.e. like matlab linux), the reason is to get the spacing to be the same (words that fit in the linux/plastic don’t fit in the apple because they have a check etc in them and I can’t change the colors of some of the apple uicontrols). When I try to reset everything I get all kinds or java exceptions, so I don’t want to change the matlab desktop. Does anyone know the minimum amount of stuff I need to just change the appearance of the uicontrols and uipanels to plastic?
Which of the following (I grabbed all the ones with com.jgoodies in them plus any others) would I need? (would I need menu items for popup menus or just the menu bar?)
@Keith – As I mentioned in the main article, you can modify the L&F of specific components, without affecting the Matlab Desktop. To do this, simply modify the L&F immediately before creating your GUI component, and restore the original L&F afterward (note how you can use either the L&F class name or its class reference):
If you modify the main L&F’s property using
javax.swing.UIManager.put()
as you attempted, it would also affect the corresponding control used in the Desktop, so this will not really help you, even if you do find the specific property to update.@Yair I tried that, testing on linux setting the L&F to metal creating the gui objects and then switching back to plastic had things look like plastic, I think that the even though the call to create the uicontrols etc went out first, there was a time delay and they weren’t being created until after it switched back to plastic, will drawnow force gui object to be drawn?
yes – add a pause(0.1) if drawnow is not enough
Hey guys, if you’re running Xubuntu like I am with the greybird GTK2 theme, you probably hate that piss-yellow background color.
Solution: place this into a file called startup.m in /usr/local/matlab/R2011a/toolbox/startup.m (if that’s where matlab is installed, that is) so that this executes on startup.
Kudos to both Yair and ZOMGxuan, thank you both for a more professional looking matlab 😀
Hi Yair, this is very helpful.
On Mac OS 10.8 (and probably 10.7) the slider component no longer has buttons for moving a single increment. This is problematic for some of our older GUIs. Does anyone know a specific property setting that can be tweaked to get back the slider buttons, or should I just use metal for the whole component?
To people trying to use GTK LaF, I have some experience with this outside of Matlab and I have found that the GTK LaF has inconsistent behavior compared to others. E.g., user actions that trigger certain callbacks consistently in windows, mac, and metal LaF do not trigger those same callbacks in GTK LaF. This is within a pretty big and messy GUI application, so it’s possible if you stick to less convoluted triggerings you will be fine, but something to be aware of.
Consulting your excellent book, sounds like I may need to use findjobj or create the slider directly from Java? Correct me if I’m wrong. Otherwise I think I’m going to punt and just set to Metal when creating these sliders. Any way to detect what version of Aqua LaF is available so I know whether the revert to Metal is necessary?
@Peter – there is no standard way to get the plaf’s version. In some cases it is included in the plaf’s Description, in others it is a property in the Defaults map, in others it is not available at all.
Re your earlier question on the slider, you could sift through the plaf’s Defaults map, to see whether there is a corresponding property that you can set. You can use Malcolm Lidierth’s excellent MUtilities package to help you with all this.
another possibility to change the lookAndFeel is to remove the jgoodies-looks.jar in /usr/local/MATLAB/R2012a/java/jarext and create a symbolic link to the one that is shipped with your distribution:
sudo ln -s /usr/share/java/jgoodies-looks.jar ./jgoodies-looks.jar
@clktmr – that’s a neat one for Linux – thanks!
[…] 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 […]
[…] I have other two links with information about it, but I don’t know how to get it. http://undocumentedmatlab.com/blog/modifying-matlab-look-and-feel/ […]
[…] I have other two links with information about it, but I don’t know how to get it. http://undocumentedmatlab.com/blog/modifying-matlab-look-and-feel/ […]
[…] 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. […]
Hi Yair,
with the recent upgrade of DEPLOYTOOL, now it is possible to compile the source code in executable file with custom icon.
Is it possible to set the icon also by compiling the source code by using MCC command?
Thanks for the answer and for your amazing books
@AIM (AIM-120?) – I do not have access to the latest Matlab Compiler, so I’m afraid that I cannot answer this… I suggest that you ask this of MathWorks support.
Hi there!
Thanks for the article.
I’m trying to modify L&F style in one of my GUIs, but I’m running into a weird problem. Here’s the problem:
I update L&F early in my code (before creating the main layout of my GUI), and later on I restore the original one according to what you have suggested in the article. When I run the code for the time, it works perfectly, but if I try to use another L&F style and run the code for the second time, the original L&F style won’t be restored. Do you have any suggestion for fixing that problem?