My findjobj utility, created in 2007 and updated over the years, has received wide recognition and is employed by numerous Matlab programs, including a few dozen utilities in the Matlab File Exchange. I am quite proud of this utility and find it extremely useful for customizing Matlab controls in many ways that are impossible using standard Matlab properties. I have shown many examples of this in this blog over the past years.
I am happy to announce that I have just uploaded a new version of findjobj to the Matlab File Exchange, which significantly improves the utility’s performance for the most common use-case of a single input and a single output, namely finding the handle of the underlying Java component (peer) of a certain Matlab control:
>> hButton = uicontrol('String','click me!'); >> tic, jButton = findjobj(hButton); toc % old findjobj Elapsed time is 1.513217 seconds. >> tic, jButton = findjobj(hButton); toc % new findjobj Elapsed time is 0.029348 seconds.
The new findjobj is backward-compatible with the old findjobj and with all prior Matlab releases. It is a drop-in replacement that will significantly improve your program’s speed.
The new version relies on several techniques:
First, as I showed last year, in HG2 (R2014 onward), Matlab uipanels have finally become full-featured Java
JPanels, that can be accessed and customized in many interesting manners. More to the point here, we can now directly access the underlying
JPanel component handle using the uipanel‘s hidden JavaFrame property (thanks to MathWorks for supplying this useful hook!). The new findjobj version detects this and immediately returns this handle if the user specified a uipanel input.
I still do not know of any direct way to retrieve the underlying Java component’s handle for Matlab uicontrols, this has been a major frustration of mine for quite a few years. So, we need to find the containing Java container in which we will recursively search for the control’s underlying Java handle. In the old version of finjobj, we retrieve the containing figure’s
JFrame reference and from it the
ContentPane handle, and use this handle as the Java container that is recursively searched. This is quite slow when the figure window is heavily-laden with multiple controls. In the new version, we try to use the specified Matlab uicontrol‘s direct parent, which is very often a uipanel. In this case, we can directly retrieve the panel’s
JPanel reference as explained above. This results in a must smaller and faster search since we need to recursively search far fewer controls within the container, compared to the figure’s
In addition, I used a suggestion by blog reader Hannes for a faster recursive search that uses the control’s tooltip rather than its size, position and class. Finally, the search order is reversed to search backward from the last child component, since this is the component that will most often contain the requested control peer.
Feel free to download and use the new findjobj version. The code for the fast variant can be found in lines #190-205 and #3375-3415.
p.s. – as I explained last week, today’s discussion, and in general anything that has to do with Java peers of GUI controls, only relates to the existing
JFrame-based figure windows, not to the new web-based uifigure.
First off thank you for this post, and all the other articles the are very interesting, and i have learned a lot out of it.
Today I downloaded this updated findjobj file, and when running it in Matlab R2015A it gave the following error.
For the moment I simply solved it by commenting this line, but this is maby not the best solution. So I was wondering if you have any tips to solve this? Is not a very important thing but i thought it was good to let you know.
Kudos on the good work and on your meticulous maintenance. It helps a lot.
One small thing though:
findjobjstill doesn’t accept the
grootobject. For example (Matlab R2015b),
Nevertheless, the old syntax still works:
I’ve been using your excellent utility in a deployed toolbox for about a year now.
Anyway, when I updated, I know get the following error
This seems to be related to this call:
This call has worked without issue in an older version of |findjobj| (% $Revision: 1.46 $ $Date: 2015/01/12 13:54:47 $)
I’m also directed to a MW page about deprecating JFrame support.
Any thoughts would be most appreciated!