Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Faster findjobj

April 11, 2016 11 Comments

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.

>> 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 ContentPane.
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.
Enjoy!
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.

Related posts:

  1. FindJObj – find a Matlab component's underlying Java object – The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
  2. FindJObj GUI – display container hierarchy – The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....
  3. Faster csvwrite/dlmwrite – The speed of the builtin csvwrite, dlmwrite functions can be improved dramatically. ...
  4. Additional uicontrol tooltip hacks – Matlab's uicontrol tooltips have several limitations that can be overcome using the control's underlying Java object....
  5. The javacomponent function – Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...
  6. Uicontrol callbacks – This post details undocumented callbacks exposed by the underlying Java object of Matlab uicontrols, that can be used to modify the control's behavior in a multitude of different events...
FindJObj GUI Java JavaFrame Undocumented feature Undocumented property
Print Print
« Previous
Next »
11 Responses
  1. Sjoerd April 18, 2016 at 12:17 Reply

    Hi Yair

    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.

    >> findjobj
    findjobj: Number of elements in right hand side does not match number required
    by left hand side
     
    Error in findjobj (line 278)
                handles  (dataLen+1:end) = [];

    >> findjobj findjobj: Number of elements in right hand side does not match number required by left hand side Error in findjobj (line 278) handles (dataLen+1:end) = [];

    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.

    Sjoerd

  2. Yaroslav April 18, 2016 at 19:25 Reply

    Hi Yair,

    Kudos on the good work and on your meticulous maintenance. It helps a lot.

    One small thing though: findjobj still doesn’t accept the groot object. For example (Matlab R2015b),

    >> findjobj(groot)
    findjobj: The following error occurred converting from matlab.ui.Root to handle:
    Conversion to handle from matlab.ui.Root is not possible.
     
    Error in findjobj/traverseContainer (line 523)
            handles(thisIdx) = handle(jcontainer,'callbackproperties');
     
    Error in findjobj (line 277)
                traverseContainer(container,0,1);

    >> findjobj(groot) findjobj: The following error occurred converting from matlab.ui.Root to handle: Conversion to handle from matlab.ui.Root is not possible. Error in findjobj/traverseContainer (line 523) handles(thisIdx) = handle(jcontainer,'callbackproperties'); Error in findjobj (line 277) traverseContainer(container,0,1);

    Nevertheless, the old syntax still works:

    >> findjobj(0)
     
    ans =
     
    	handle: 1-by-1170

    >> findjobj(0) ans = handle: 1-by-1170

    Cheers

  3. Meade August 29, 2016 at 23:29 Reply

    Hi Yair,

    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

    Java exception occurred:
    java.lang.ArrayIndexOutOfBoundsException: No such child: 4
    	at java.awt.Container.getComponent(Unknown Source)

    Java exception occurred: java.lang.ArrayIndexOutOfBoundsException: No such child: 4 at java.awt.Container.getComponent(Unknown Source)

    This seems to be related to this call:

    jscroll = findjobj(MyUitable)  %get jScroll UI element under Matlab table
    rhv = jscroll.getComponent(4);

    jscroll = findjobj(MyUitable) %get jScroll UI element under Matlab table rhv = jscroll.getComponent(4);

    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!
    Best,
    Meade

    • Yair Altman September 6, 2016 at 19:21 Reply

      @Meade – as you can see, the error is not in the findjobj call but in your code (jscroll.getComponent(4)). You need to check the jscroll object that findjobj returned and see why there is no 5th component (Java indexes start from 0, so “4” means “5th”). You can do something like this:

      >> jscroll = findjobj(MyUitable)
      >> jscroll.list

      >> jscroll = findjobj(MyUitable) >> jscroll.list

      • Meade September 22, 2016 at 16:21

        @Yair – Thanks so much for the reply.
        I’ve been using your .list tip to dig into this more deeply and it seems that the new findjobj function returns a different (shorter) list of components than the older revision. This seems to be why my subsequent call for

        jscroll.getComponent(4);

        jscroll.getComponent(4);

        fails.
        For example:

        jscroll = findobj(info);
        jscroll.list

        jscroll = findobj(info); jscroll.list

        yields:

        com.mathworks.hg.peer.utils.UIScrollPane[, 0, 0, 0x0, invalid, ..., viewportBorder = ]
        javax.swing.JViewport[, 0, 0, 0x0, invalid, ..., scrollUnderway = false]
        com.mathworks.hg.peer.ui.UITablePeer$23[hInfoTable, 0, 0, 0x0, invalid, ..., showHorizontalLines = true, showVerticalLines = true]
        javax.swing.CellRendererPane[, 0, 0, 0x0, invalid, hidden]
        com.mathworks.hg.peer.utils.UIScrollPane$1[, 0, 0, 0x0, invalid, ..., blockIncrement = 10, orientation = VERTICAL, unitIncrement = 1]
        com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true]
        com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true]
        com.mathworks.hg.peer.utils.UIScrollPane$2[, 0, 0, 0x0, invalid, ..., blockIncrement = 10, orientation = HORIZONTAL, unitIncrement = 1]
        com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true]
        com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true]

        com.mathworks.hg.peer.utils.UIScrollPane[, 0, 0, 0x0, invalid, ..., viewportBorder = ] javax.swing.JViewport[, 0, 0, 0x0, invalid, ..., scrollUnderway = false] com.mathworks.hg.peer.ui.UITablePeer$23[hInfoTable, 0, 0, 0x0, invalid, ..., showHorizontalLines = true, showVerticalLines = true] javax.swing.CellRendererPane[, 0, 0, 0x0, invalid, hidden] com.mathworks.hg.peer.utils.UIScrollPane$1[, 0, 0, 0x0, invalid, ..., blockIncrement = 10, orientation = VERTICAL, unitIncrement = 1] com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true] com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true] com.mathworks.hg.peer.utils.UIScrollPane$2[, 0, 0, 0x0, invalid, ..., blockIncrement = 10, orientation = HORIZONTAL, unitIncrement = 1] com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true] com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true]

        While

        jscrollOLD = findobjOLD(info);
        jscrollOLD.list

        jscrollOLD = findobjOLD(info); jscrollOLD.list

        yields:

        com.mathworks.hg.peer.utils.UIScrollPane[, 0, 0, 500 x140, invalid, ..., viewportBorder = ]
        javax.swing.JViewport[, 375, 1, 124 x121, invalid, ..., scrollUnderway = false]
        com.mathworks.hg.peer.ui.UITablePeer$23[hInfoTable, 0, 0, 397 x120, invalid, ..., showHorizontalLines = true, showVerticalLines = true]
        javax.swing.CellRendererPane[, 0, 0, 0x0, invalid, hidden]
        com.mathworks.hg.peer.utils.UIScrollPane$1[, 0, 0, 0x0, invalid, hidden, ..., blockIncrement = 10, orientation = VERTICAL, unitIncrement = 1]
        com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true]
        com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true]
        com.mathworks.hg.peer.utils.UIScrollPane$2[, 375, 122, 124 x17, invalid, ..., blockIncrement = 10, orientation = HORIZONTAL, unitIncrement = 1]
        com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 107, 0, 17 x17, invalid, ..., defaultCapable = true]
        com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 17 x17, invalid, ..., defaultCapable = true]
        javax.swing.JViewport[, 375, 1, 124 x0, invalid, ..., scrollUnderway = false]
        javax.swing.JLabel[, 1, 1, 374 x0, invalid, ..., verticalAlignment = CENTER, verticalTextPosition = CENTER]

        com.mathworks.hg.peer.utils.UIScrollPane[, 0, 0, 500 x140, invalid, ..., viewportBorder = ] javax.swing.JViewport[, 375, 1, 124 x121, invalid, ..., scrollUnderway = false] com.mathworks.hg.peer.ui.UITablePeer$23[hInfoTable, 0, 0, 397 x120, invalid, ..., showHorizontalLines = true, showVerticalLines = true] javax.swing.CellRendererPane[, 0, 0, 0x0, invalid, hidden] com.mathworks.hg.peer.utils.UIScrollPane$1[, 0, 0, 0x0, invalid, hidden, ..., blockIncrement = 10, orientation = VERTICAL, unitIncrement = 1] com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true] com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 0x0, invalid, ..., defaultCapable = true] com.mathworks.hg.peer.utils.UIScrollPane$2[, 375, 122, 124 x17, invalid, ..., blockIncrement = 10, orientation = HORIZONTAL, unitIncrement = 1] com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 107, 0, 17 x17, invalid, ..., defaultCapable = true] com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[, 0, 0, 17 x17, invalid, ..., defaultCapable = true] javax.swing.JViewport[, 375, 1, 124 x0, invalid, ..., scrollUnderway = false] javax.swing.JLabel[, 1, 1, 374 x0, invalid, ..., verticalAlignment = CENTER, verticalTextPosition = CENTER]

        I’m sure that I’m missing something obvious, but any insight you have would be greatly appreciated.
        (As a final note, curiously, if I call the older version of findjobj first, then the newer version will successfully find all components. Thus, there is some sort of order dependence?! Weird!

        Thanks so much,
        Meade

    • Malcolm Lidierth September 23, 2016 at 02:46 Reply

      @Meade
      Not sure about this. Are your components on the EDT? Are the components visible? You might try a drawnow() and see if that order dependence disappears. Also see javaObjectEDT.
      ML

      • Meade September 23, 2016 at 17:33

        @Malcolm
        I do not know if they are all on EDT. I’m an absolute java novice, but from reading, I cannot say whether all components are being accessed in the same thread. This seems like a question that Yair might be able to answer since all the calls are being made within the findjobj call.

        I understand this all seems stranges, but I get the errors while literally only changing the version of findjobj that is being used, so the difference must be related to that. I’m happy/willing/excited to make changes since Yair has made such dramatic speed improvements in his utility, I’m just at a loss as where to start.

        Thanks for all the good suggestions.
        Meade

    • Malcolm Lidierth September 23, 2016 at 22:02 Reply

      Meade

      Create your JScrollPane through a call to
      >> jscroll=javaObjectEDT(‘javax.swing.JScrollPane’);

      That on it’s own might(??) fix all your problems as subsequent methods calls to the scroll pane should be despatched via the EDT. If not do post your construction code. Very few Swing methods are inherently thread-safe and this does look like a treading issue.

  4. Meade September 26, 2016 at 23:26 Reply

    @Malcolm,

    You’ve got my attention! My situation is that the JScrollPane is actually created by the uitable command. Is it possible to tweak this matlab command in order to accomplish what you’ve suggested? I was hoping to avoid a pure java creation, since I’m more comfortable creating the gui using Matlab methods.
    %(begin code)

    info = uitable('Parent',hLeft,...
        'Data',cell(5,1),...
        'ColumnName', [],...
        'RowName',infoCell,...
        'RowStriping','off',...
        'ColumnWidth', {397},...
        'ColumnFormat', columnformat,...
        'ColumnEditable', false,...
        'Position',[30, 10, 500, 140 ],...
        'FontSize',10,...
        'TooltipString',TTstr.TSVinfo,...
        'BackgroundColor',[0.94 0.94 0.94],...
        'Tag','hInfoTable');
     
    %%% Java voodoo for Info table
    jscroll=findjobj(info);

    info = uitable('Parent',hLeft,... 'Data',cell(5,1),... 'ColumnName', [],... 'RowName',infoCell,... 'RowStriping','off',... 'ColumnWidth', {397},... 'ColumnFormat', columnformat,... 'ColumnEditable', false,... 'Position',[30, 10, 500, 140 ],... 'FontSize',10,... 'TooltipString',TTstr.TSVinfo,... 'BackgroundColor',[0.94 0.94 0.94],... 'Tag','hInfoTable'); %%% Java voodoo for Info table jscroll=findjobj(info);

    % end code

    Thanks again for all the help.
    Meade

    • Malcolm Lidierth September 27, 2016 at 02:55 Reply

      @Meade

      You can call jscroll methods in the EDT if you can get a reference to it and call javaObjectEDT on the reference:

      jscroll=javaObjectEDT(jscroll)

      jscroll=javaObjectEDT(jscroll)

      If you have problems after a javaObjectEDT you might try

      jscroll.revalidate();% Does layout
      jscroll.repaint();% Paints component
      drawnow()

      jscroll.revalidate();% Does layout jscroll.repaint();% Paints component drawnow()

      Revalidate and repaint are both thread-safe and will be run on the EDT by Swing.

      I am on a Mac and all seems to work fine without tweaks (and the same with the latest or older findjobj) so I can’t be much help but here’s what I see anyway:

      >> info = uitable('Parent',figure,...
          'Data',cell(5,1),...
          'ColumnName', [],...
          'RowName',{'1', '2', '3','4','5'},...
          'RowStriping','off',...
          'ColumnWidth', {397},...
          'ColumnEditable', false,...
          'Position',[30, 10, 500, 140 ],...
          'FontSize',10,...
          'BackgroundColor',[0.94 0.94 0.94],...
          'Tag','hInfoTable');
      >> jscroll=findjobj(info)
       
      jscroll =javahandle_withcallbacks.com.mathworks.hg.peer.utils.UIScrollPane

      >> info = uitable('Parent',figure,... 'Data',cell(5,1),... 'ColumnName', [],... 'RowName',{'1', '2', '3','4','5'},... 'RowStriping','off',... 'ColumnWidth', {397},... 'ColumnEditable', false,... 'Position',[30, 10, 500, 140 ],... 'FontSize',10,... 'BackgroundColor',[0.94 0.94 0.94],... 'Tag','hInfoTable'); >> jscroll=findjobj(info) jscroll =javahandle_withcallbacks.com.mathworks.hg.peer.utils.UIScrollPane

      All seems OK to me:

      >> jscroll.getComponents()
       
      ans =
       
        java.awt.Component[]:
       
          [1×1 javax.swing.JViewport                     ]
          [1×1 com.mathworks.hg.peer.utils.UIScrollPane$1]
          [1×1 com.mathworks.hg.peer.utils.UIScrollPane$2]
          [1×1 javax.swing.JViewport                     ]
          [1×1 javax.swing.JViewport                     ]
          [1×1 javax.swing.JList                         ]

      >> jscroll.getComponents() ans = java.awt.Component[]: [1×1 javax.swing.JViewport ] [1×1 com.mathworks.hg.peer.utils.UIScrollPane$1] [1×1 com.mathworks.hg.peer.utils.UIScrollPane$2] [1×1 javax.swing.JViewport ] [1×1 javax.swing.JViewport ] [1×1 javax.swing.JList ]

  5. claudio June 2, 2017 at 23:25 Reply

    Hi Yair,

    thanks a lot for your work!
    I built a figure with some tabs. in one specific tab i set another small uitabgroup (and tabs) to show some tables.
    I can’t take the uitabgroup handle from command window (empty value is returned) but I can see the “object” and
    modify all his properties from findjobj window.
    what is the problem? how can I continue to use findjobj from command window also in this case?

    best regards
    claudio

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitable (6) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top