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