Over the past few years I have shown numerous uses of Java components in Matlab, many of them built-into the Matlab environment and can be used as-is. I have been asked many times how I uncover these components and how I discover how to use them. The short answer is that this is indeed often not easy. The blog articles (and my book) only present “success stories“, i.e. cases where I was able to uncover the behavior, functionality and usage of such components; they do not present the numerous other cases where I have not been so successful.
Still, over the course of the past 10-15 years, I developed several tools that help me become more efficient in this work, and I’ve posted most of these on the File Exchange. I’ve already written here about the FindJObj utility, both as a means for uncovering the underlying Java reference of Matlab GUI controls, and as a means to visualize the GUI hierarchy of a specified window or container. I also wrote about my uiinspect utility, which analyzes the specified object in a compact and intuitive GUI window.
Today I wish to complete the picture by describing my checkClass utility. checkClass is more limited than uiinspect in the types of objects that it can analyze (almost only Java objects) and the information that it presents (for example, callbacks and properties are not listed separately). checkClass‘s main benefit is the fact that it is a very lightweight (230 lines of code), fast, GUI-less console application. checkClass highlights the differences between the analyzed class and its superclass, which is especially useful when investigating the functionality of objects. During the course of my work, I use checkClass for 95% of my investigations, and uiinspect/findjobj only for the remainder. For Java objects at least, a detailed console listing of the methods is quite enough, since properties are typically accessed via getPropName()/setPropName() accessor methods. The combination of checkClass and uiinspect can be very useful when investigating a new Java library or integrating a 3rd-party API.
Here is a sample output for the
>> jButton = com.mathworks.mwswing.MJToggleButton; >> checkClass(jButton) % or: jButton.checkClass Class com.mathworks.mwswing.MJToggleButton (uiinspect) Superclass: javax.swing.JToggleButton Methods in MJToggleButton missing in JToggleButton: hasFlyOverAppearance() : boolean hideText() isAutoMnemonicEnabled() : boolean isTextHidden() : boolean setAutoMnemonicEnabled(boolean) setFlyOverAppearance(boolean) setFocusTraversable(boolean) unHideText() Methods inherited & modified by MJToggleButton: getForeground() : java.awt.Color getParent() : java.awt.Container isFocusTraversable() : boolean paint(java.awt.Graphics) setAction(javax.swing.Action) setModel(javax.swing.ButtonModel) setText(java.lang.String) Interfaces in JToggleButton missing in MJToggleButton: javax.accessibility.Accessible Interfaces in MJToggleButton missing in JToggleButton: com.mathworks.mwswing.ExtendedButton
The interpretation is quite intuitive. For example, isTextHidden() is a class method that accepts no input args and returns a boolean result; setText() is a method that accepts a string and returns no result.
Each of the hyperlinks is linked to another checkClass on the specified class. This makes investigation of classes and their interconnections quite easy.
From this output, we learn that the MathWorks
MJToggleButton class added the FlyOverAppearance and AutoMnemonicEnabled properties, together with their associated accessor methods. We also learn that
MJToggleButton added a non-property method: hideText().
Finally, setFocusTraversable() was added as a setter method to the FocusTraversable property: the getter method isFocusTraversable() is already defined in the ancestor
JToggleButton class (which is part of the standard Swing package) –
MJToggleButton simply added a setter method.
Some classes (e.g.,
MJSlider) appear to be plain wrappers for their Swing ancestor:
>> checkClass('com.mathworks.mwswing.MJSlider') Class com.mathworks.mwswing.MJSlider (uiinspect) Superclass: javax.swing.JSlider Methods inherited & modified by MJSlider: setModel(javax.swing.BoundedRangeModel) Interfaces in JSlider missing in MJSlider: javax.accessibility.Accessible javax.swing.SwingConstants
In other cases, MathWorks has extensively modified the base class functionality:
>> checkClass com.mathworks.mwswing.MJToolBar Class com.mathworks.mwswing.MJToolBar (uiinspect) Superclass: javax.swing.JToolBar Methods in MJToolBar missing in JToolBar: addGap() addGap(int) addToggle(javax.swing.Action) : javax.swing.JToggleButton configure(com.mathworks.mwswing.ExtendedButton) (static) configureButton(com.mathworks.mwswing.MJButton) (static) configureButton(com.mathworks.mwswing.MJToggleButton) (static) configureButton(com.mathworks.mwswing.MJToggleButton, boolean) (static) createMacPressedIcon(javax.swing.Icon) : javax.swing.Icon (static) dispose() dispose(javax.swing.JToolBar) (static) getComponentExcludingMoreButton(int) : java.awt.Component getFlyOverBorder() : javax.swing.border.Border (static) getToggleFlyOverBorder() : javax.swing.border.Border (static) isFloating() : boolean isMarkedNonEssential(javax.swing.JComponent) : boolean (static) isMorePopupEnabled() : boolean isOnMoreMenu(java.awt.Component) : boolean markAsNonEssential(javax.swing.JComponent) (static) setArmed(boolean) setInsideToolbarBorder() setMorePopupEnabled(boolean) Methods inherited & modified by MJToolBar: add(javax.swing.Action) : javax.swing.JButton addSeparator() addSeparator(java.awt.Dimension) doLayout() getMinimumSize() : java.awt.Dimension getPreferredSize() : java.awt.Dimension removeAll() Interfaces in JToolBar missing in MJToolBar: javax.accessibility.Accessible javax.swing.SwingConstants Static fields in MJToolBar missing in JToolBar: MORE_BUTTON_NAME = 'MoreButton' MORE_MENU_INELIGIBLE_PROPERTY_KEY = 'MoreMenuIneligible' NON_ESSENTIAL_PROPERTY_KEY = 'NonEssentialComponent' Sub-classes in MJToolBar missing in JToolBar: com.mathworks.mwswing.MJToolBar$VisibleSeparator
In this example, we see that the
MJToolBar class includes 3 variants for the configureButton() method, and 2 variants for the dispose() method, accepting a different number and/or type of input parameters.
Similarly, for the
>> checkClass com.mathworks.mwswing.checkboxlist.CheckBoxList Class com.mathworks.mwswing.checkboxlist.CheckBoxList (uiinspect) Superclass: com.mathworks.mwswing.MJList Superclass: javax.swing.JList Methods in JList missing in CheckBoxList: JList(java.lang.Object) JList(java.util.Vector) Methods in CheckBoxList missing in JList: CheckBoxList(java.util.List) checkAll() checkIndex(int) checkValue(java.lang.Object) constrainViewerToCellHeight() : boolean getCellPainter(java.lang.Integer) : java.awt.Component getCellPainter(java.lang.Object) : java.awt.Component getCellViewerOffset(java.lang.Integer) : java.awt.Dimension getCellViewerOffset(java.lang.Object) : java.awt.Dimension ...
Here we see that two superclass constructor variants (accepting an array of
Objects or a single
Vector object) have been replaced by a single constructor that accepts a
List object (this is considered a bad programming practice, by the way).
In this case,
MJList which is also a Matlab class, which itself extends the standard Swing
JList. By default, checkClass compares the specified class object versus the nearest ancestor class that is non-MathWorks. We can modify this behavior by specifying a different super-class level:
>> checkClass('com.mathworks.mwswing.checkboxlist.CheckBoxList', 1) % compare CheckBoxList to com.mathworks.mwswing.MJList >> checkClass('com.mathworks.mwswing.checkboxlist.CheckBoxList', 2) % compare CheckBoxList to javax.swing.JList (=default behavior) >> checkClass('com.mathworks.mwswing.checkboxlist.CheckBoxList', 3) % compare CheckBoxList to javax.swing.JComponent (=JList's superclass) >> checkClass('com.mathworks.mwswing.checkboxlist.CheckBoxList', 4) % compare CheckBoxList to java.awt.Container (=JComponent's superclass) % ...and so on (up to java.lang.Object, which is the base class for all Java objects)
checkClass can inspect both class name and class objects. For example:
checkClass('java.lang.String') % class name checkClass(javax.swing.JButton) % class object jButton = javax.swing.JButton('Click me!'); jButton.checkClass; % class object checkClass('com.mathworks.mwswing.MJToolBar') % class-name checkClass(com.mathworks.mwswing.MJToolBar) % class object checkClass(com.mathworks.mde.desk.MLDesktop.getInstance)
Class methods can also be inspected using methodsview or preferably uiinspect; properties and callbacks can be inspected by using get, inspect, or again uiinspect. Users may also try to search the Matlab-supplied m-files for sample usage of these classes. For example, Matlab 7.2’s uisetfont.m uses
com.mathworks.mwswing.MJButton. Note that different Matlab releases use internal classes differently. Therefore, searching the m-file code base of different Matlab releases may yield additional clues.
I encourage you to download the checkClass utility and explore its code, and I welcome your feedback.
p.s. – Anyone watching the TV series “The Americans” may have noticed that in the season finale (“Echo“), which aired on May 21, the code listing of the Echo program, is actually that of a GUIDE-created Matlab m-file (linear_array_gui), plus some non-Matlab code (Ada?). Matlab’s GUIDE wasn’t available in the mid-1980s, when the story purportedly takes place, back in the days of a 640KB IBM PC with a single floppy drive, but it’s a nice anachronism. In any case the combination of the Matlab and Ada code would never have run… 🙂