In my previous post, I explained how the findjobj utility can be used to access a Matlab component’s underlying Java component. Findjobj has another role: displaying the component hierarchy of complex Matlab containers such as the figure window, GUIDE or the Editor.
When findjobj is called with no output arguments, the function infers that the user requests to see the GUI version, rather than to get the control’s Java handle:
>> findjobj(gcf); % or: findjobj(gcf) |
There are several note-worthy aspects in this graphical hierarchy presentation:
The hierarchy tree itself is displayed using the internal com.mathworks.hg.peer.UITreePeer Java object. This is the object that underlies the semi-documented uitree function. The hierarchy sub-components are presented as tree nodes, each having a separate icon based on the component type. In some cases (toolbar buttons for example), the component’s icon image is used for its corresponding tree node. A javax.swing.JProgressBar is presented while the tree is being populated, an action that can take a few seconds depending on the target figure’s complexity. Some tree branches which are normally uninteresting are automatically collapsed: hidden containers (these are also grayed-out), menubars, toolbars and scrollbars. In parallel to the Java container hierarchy, a separate tree branch is presented with the corresponding Matlab (Handle-Graphics, or HG) hierarchy.
Each node item gets a unique tooltip (see top screenshot above). Similarly, a unique context-menu (right-click menu) is attached to each node item with actions that are relevant for that node:
Finally, a node-selection callback is attached to the tree, that will flash a red border around the GUI control when its corresponding Java node-item is clicked/selected:
Once the tree was done, I set out to display and enable modifications of component properties and callbacks in separate adjacent panels. I used the internal com.mathworks.mlwidgets.inspector.PropertyView component to display the properties (this is the JIDE component that underlies the built-in inspect function). To prevent a JIDE run-time alert, I called com.mathworks.mwswing.MJUtilities.initJIDE. A label is added to the table’s header, displaying the currently selected sub-component’s class (e.g., “javax.swing.JButton”), and a tooltip with a color-coded list of all the control’s properties.
The callbacks table was implemented using com.jidesoft.grid.TreeTable to enable easy column resizing, but this is otherwise used as a simple data table. A checkbox was added to filter out the 30-odd standard Swing callbacks, which are non-unique to the selected sub-component (tree node). All the panels – tree, properties and callbacks – are then placed in resizable javax.swing.JSplitPanes and presented to the user.
I have omitted mention of some other undocumented features in findjobj. After all, space here is limited and the function is over 2500 lines long. I encourage you to download the utility and explore the code, and I gladly welcome your feedback.
[…] The Matlab inspector can be embedded, with not-too-much effort, within Matlab GUI applications. Examples of this can be found in the FindJObj and UIInspect utilities. […]
Hi
I really love this tool. Perfect! One question – I really did not find it out myself. How do you manage the resize behavior of the tree pane? I.e. that you can move over the mouse on the tree pane and adjust it to make it less wide?
Best Regards,
Patrice
@Patrice – findjobj uses JSplitPanes, which enable easy resizing of the left/right or top/bottom panes. I simply placed the tree in the top left pane and the JSplitPane control took care of the rest. Easy.
Hey,
Is there no “easier” or quicker way to find the underlying java object/handle to my hg object then using findjobj?
I mean, I gave it a try and took a look at the findjobj() function. It is indeed a mighty tool. But its also a blown up one. As far as I could find out, it tries to list all child components of my figure to find the requested handle. Ofcourse, this consumes time.
In addition, it must make the figure visible to be able to find all children. This may be distracting for users. Lets say the figure is not visible during initilization. However, when my code hits the part where I am looking for my java object, the figure is made visible and invisible again by findjobj(). Yes, the figure is actually not visible because it gets positioned outside the screen, yet the icon for the figure in the windows taskbar briefly appears and then disappeares. You know what I mean? This can be in particular distracting when I must call findjobj() several times.
Is there a workaround for this?
Regards
Hannes
@Hannes – perhaps there is a simpler way but I am not aware of it. If you ever discover such a way, let me know and I’ll be happy to scrap findjobj. Until then, this is the only game in town. So you should direct your complaints to MathWorks for not exposing a simpler way, rather than to me…
@Yair — That wasn’t a complain at all! Just wondering ;). Maybe sometimes the guys at MathWorks wonder, too. After all, its not that big of deal. Thank your for your quick reply :).
Cheers
Hannes
@Yair — Sleep eluded me over the last 2 nights because of this problem. Hence, I used your findjobj() tool to work myself into the Java-UI-tree findjobj(gcf) provides. Maybe I found a plain way to get what I want: to have a function that returns the underlying Java UI component to a uicontrol (handle), without having to confront the problem I previously described.
I know its neither a foolproof tool nor a very robust one. Still, it works for my problem very well.
That’s my take on it.
http://hpewd.dorado.uberspace.de/getUIcontrolJHandle.m
Maybe you find some time to take a look on it :).
Thank your for your advice and great tool findjobj().
Best regards
Hannes