FindJObj – find a Matlab component’s underlying Java object

In a previous post, I explained that all Matlab GUI (except the axes plotting engine) is based on Java components, and showed how we can use this information to display HTML contents in Matlab uicontrols. In other posts, I have shown how a utility called findjobj can be used to access the underlying Java components to enable customizations that are unavailable in standard Matlab: setting the line location in an edit-box, customizing button appearance, setting uicontrol callbacks, or setting list-box mouse actions. I have also shown how findjobj can be used to display the component hierarchy of complex Matlab containers such as the figure window, GUIDE or the Editor.

The time is therefore well overdue for a formal introduction of findjobj, explaining its uses and internal mechanism. Of course, readers are welcome to continue using findjobj as a black-box utility, but I think important insight can be gained from understanding its inner details. Findjobj‘s code is available for free download on the MathWorks File Exchange. It is one of my favorite submissions and is apparently well-liked by users, being highly reviewed and highly downloaded.

Findjobj has two main purposes:

  1. Find the underlying Java object reference of a given Matlab handle – Historically this was the original purpose, hence the utility’s name. Findjobj was meant to extend Matlab’s standard findobj function, which does not expose Java components.
  2. Display a container’s internal components hierarchy in a graphical user interface, to facilitate visualization of complex containers. This was later extended to also display and allow modification of the sub-components’ properties and callbacks.

Today I will focus on the first (programmatic) aspect; next week I will describe the second (GUI) aspect.

Findjobj‘s heart is finding a control’s underlying Java handle. Unfortunately, this is not exposed by Matlab except in very rare cases. As hard as I tried, I could not find a way to directly access the underlying Java-peer handle. I therefore resorted to getting the control’s enclosing Java frame (window) reference, and then working down its sub-components hierarchy until finding the Java object(s) which satisfy the position and/or class criteria. To get the enclosing Java frame (aka TopLevelAncestor), I use the Matlab figure’s undocumented JavaFrame property. Using this property issues a standard warning (since Matlab release R2008a) of becoming obsolete in some future Matlab release. Since it worked so far, I have turned off this warning in findjobj‘s code, but note that this code may well fail in some future Matlab version. If and when JavaFrame does become obsolete, be sure to look in this blog for workarounds…

Traversing the frame’s hierarchy presents several challenges: Main-menu items are accessed using different functions than other Swing components or sub-containers, and are not automatically accessible until first displayed. I have overcome this latter challenge by simulating a menu-open action in case menus should be searched (this is off by default since it takes several seconds and also changes the GUI focus). For “regular” sub-containers, sometimes we need to loop over getComponent(…) and in some other cases over getChildAt(…).

Another challenge was presented by the fact that Java positions start at (0,0) in the top left corner increasing rightward and downward, rather than starting at (1,1) in the bottom left and increasing upward as in Matlab. Moreover, Java positions are always pixel-based and relative to their parent container, which is different from Matlab (if the Matlab units is ‘pixels’ then the value is absolute; if ‘normalized’ then it returns a non-pixel value). To further complicate matters, some Matlab controls have a different size than their Java counterparts: some controls have a 5-pixel margins while others not, some controls are shifted by a pixel or two from their container’s border (for a total offset of up to 7 pixels), while some controls (such as popup-menus) have an entirely different reported size. In theory, we could use the Matlab component’s undocumented PixelBounds property (much faster than getpixelposition), but unfortunately PixelBounds turns out to be unreliable and returns erroneous values in many cases. Finally, different Java containers/components have different ways of returning their position: for some it is a getLocation() method, for others it is getX()/getY() and for others it is the X and Y properties (that sometimes have no corresponding getX()/getY() accessor methods!).

Having finally overcome all these challenges (and quite a few smaller ones, documented within the source code), I have wrapped the algorithm in a function interface that tries to emulate findobj‘s. Using findjobj can now be as easy as:

% Modify the mouse cursor when over the button
hButton = uicontrol('string','click me!');
jButton = findjobj(hButton);
jButton.setCursor(java.awt.Cursor(java.awt.Cursor.HAND_CURSOR))

Modified uicontrol cursor - a Java property

Modified uicontrol cursor - a Java property

…or as complex as:

% Find all non-button controls with the specified label
jControls = findjobj('property',{'text','click me!'}, 'not','class','button');

Space here is limited and findjobj is over 2500 lines long, so I have obviously not covered everything. I encourage you to download the utility and explore the code, and I gladly welcome your feedback.

Related posts:

  1. 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....
  2. Setting status-bar components Matlab status-bars are Java containers in which we can add GUI controls such as progress-bars, not just simple text labels...
  3. Assessing Java object size in Matlab Java object sizes are not reported by Matlab, but we can still estimate them using two free external utilities. ...
  4. Date selection components The JIDE package, pre-bundled in Matlab, contains several GUI controls for selecting dates - this article explains how they can be used...
  5. Plot-type selection components Several built-in components enable programmatic plot-type selection in Matlab GUI - this article explains how...
  6. Color selection components Matlab has several internal color-selection components that can easily be integrated in Matlab GUI...

Categories: Figure window, GUI, Handle graphics, High risk of breaking in future versions, Java, UI controls, Undocumented feature

Tags: , , , , , ,

Bookmark and SharePrint Print

41 Responses to FindJObj – find a Matlab component’s underlying Java object

  1. Peter says:

    Dear Yair

    Thank you very much for your great, great website. One really gets a feel for what is going on behind the scens in matlab.

    I have a few question related to the findobj application:

    You say that everything except the Java plotting engine is based on Java. I would like though to use the panelling from findobj in an application with for insatnce a matlab plot in one of the panels. Does your comment mean that I will be unsuccesful with that? If not, can you please give me a quick hint on how to get this?

    Second, when you publish fíndobj in “High risk of breaking…” what is the risk then? Does it include the panels feature that I am after or do you rather think of the more programmatic part of it?

    Thank you very much in advance!

    Peter

    • Thanks Peter.

      Unfortunately, you cannot embed a Matlab plot axis in a Java container (only Java components in a Matlab container). However, to solve this problem I have created the UISplitPane utility that behaves exactly like a Java JSplitPane, and enables interactively-resizable panels with Matlab plots:

      Two levels of UISplitPane, with customized dividers

      Two levels of UISplitPane, with customized dividers

      As for your second question, I indicated “High risk of breaking in a future version” because FindJObj is highly dependent on internal Matlab implementation, which may break without warning between Matlab releases. For example, the very next release (R2010a) might remove the JavaFrame property, on which findjobj relies. Of course, since I maintain this utility I will try to bypass the problem and upload a new version (and findjobj has an automated mechanism to detect and suggest this new version), but I cannot promise anything concrete. Some other undocumented features I believe to be less prone to breaking in future releases, and so they get a less severe warning. Note that I base the severity on gut instinct and calculated guesses – I have no official access to Matlab’s development roadmap.

    • Peter says:

      Thank you very much Yair

      I will have a look at the UIsplitpane utility. It seems more appropiate for my use.

      Thanks again. It is a real cool site you have!

      Peter

  2. Daniel says:

    Yair
    Your program is great, but I found some trouble using it. It seems like it only works with controls created by code. I tried to find underlying java object for controls created with GUIDE, and findjobj always returned empty handles arrays. it’s that posible? is there another way to find a JTextbox behind a uicontrol created with GUIDE?

    Thanks,
    Daniel

    • @Daniel – It works for me…
      Perhaps you’re calling findjobj in your _OpeningFcn() instead of in your _OutputFcn() or in callbacks? This would explain the problem, since the GUI has not yet rendered onscreen in _OpeningFcn() (the figure is still invisible), so findjobj cannot find the Java handle.

    • Daniel says:

      Yair, you’re right. I was calling it in my OpenFcn() method. My purpose was set a InputVerifier to an edit control. Is there another callback in wich i can do that?

      Thank you very much!

    • @Daniel – as I said, simply attach your InputVerifier in the _OutputFcn() instead of in the _OpeningFcn(). Both of these functions are automatically created by GUIDE: _OpeningFcn() is invoked before the figure is made visible and the Java peers are created; _OutputFcn() is invoked immediately after it’s made visible, when the peers are in place.

      I would be happy if you added a comment with your InputVerifier code, for the benefit of other readers. If the code is long, email me (altmany at gmail) and I’ll add a separate post about it.

    • Daniel says:

      Yair, i moved my code to the _OutputFcn, but findjobj still returns empty arrays. I couldn’t find out what is my error.
      i’ve written a simple code which replaces uicontrols with javax.swing.JTextFields:

      function [ output_args ] = ReemplazarControles(hObject)
      %UNTITLED2 Summary of this function goes here
      %   Detailed explanation goes here
       
          children = get(hObject,'Children');
          nSize = size(children);
          for i=1:nSize
              hControl = children(i);
              if isa(handle(hControl),'uicontrol') 
                  cStyle = get(hControl,'Style');
                  if strcmp(cStyle,'edit')==1
                      sPosition = get(hControl,'Position');
                      sUnits = get(hControl,'Units');
                      sParent = get(hControl,'Parent');
                      [text textcontainer] = javacomponent('javax.swing.JTextField',[0 0 100 100], hObject);
                      set(textcontainer,'Units','characters','Position',sPosition);
                      delete(hControl);
                  end
              end
              if isa(handle(hControl),'uipanel')
                  ReemplazarControles(hControl);
              end
          end
      end

      it works fine, but JTextFields not response Tab key strokes.
      I could use both methods. I don’t know wich is better.
      I deeply appreciate your help

  3. Peter says:

    Dear Yair

    I am sorry for this kind of java newbie question, but I am back using the panes from the findobj. Now, instead of including a figure (as I asked about above) in one of the panes I would like to put a uitable or preferably your createtable from the FEX. I have tried many approaches, but none of them successful. I would be very happy if you have any directions on how to do it or have an example.

    Thank you very much in advance!

    Best regards, Peter

  4. Pingback: Continuous slider callback | Undocumented Matlab

  5. Pingback: Tabbed panes – uitab and relatives | Undocumented Matlab

  6. Pingback: GUI integrated HTML panel | Undocumented Matlab

  7. Pingback: Customizing uicontrol border | Undocumented Matlab

  8. Sherif Elnabarawy says:

    Dear Yair , i am using findjobj to get the java handle of uitable to apply some java methods on it , but unfortunately using findjobj makes the uitabs and uitabgroups stop responding ! i can’t understand what’s going on but i hope that i am missing something so that i can fix and continue using it .
    this is code sample to show what i am talking about , try and feedback me .
    thanks a lot.

    f=figure;
    uitabgroup(f,'Tag','view_tabgroup');
    uitab('v0', findobj('Tag','view_tabgroup'), 'title', 'System Data','Tag','system_tab');
    uitab('v0',findobj('Tag','view_tabgroup'), 'title', 'Network','Tag','network_tab');
     
    uipanel(findobj('Tag','system_tab'),'BackgroundColor','black','Tag','panel1');
    uicontrol('style','pushbutton','tag','push1','parent',findobj('Tag','panel1'));
     
    jUIScrollPane=findjobj(findobj('tag','push1'));
    • @Sherif – it works ok for me on WinXP R2010b. Perhaps you forgot a call to drawnow before using findjobj, or perhaps you’re using an old version of findjobj.

    • Sherif Elnabarawy says:

      i am using WinXP R2009a , tabs is working fine until i call findjobj :S , my findjobj version is updated , called drawnow before and after findjobj , but nothing changed .
      i don’t know if the matlab version is the problem or there is something else .
      i’ll try anyway .

  9. Pingback: Tri-state checkbox | Undocumented Matlab

  10. Pingback: HG2 update | Undocumented Matlab

  11. Pingback: Variables Editor scrolling | Undocumented Matlab

  12. Pingback: Rich-contents log panel | Undocumented Matlab

  13. Pingback: Editbox data input validation | Undocumented Matlab

  14. Pingback: Editable combo-box | Undocumented Matlab

  15. Pingback: Using JIDE combo-boxes | Undocumented Matlab

  16. Pingback: Listbox layout customization | Undocumented Matlab

  17. Ruthy says:

    Hi,

    The function doesn’t work for matlab release 2013b.
    Do you know how it will be possible to adjust it to work in this release?

    Thanks!
    Ruthy

    • @Ruthy – The findjobj function works perfectly well on R2013b. It is your specific situation that perhaps doesn’t work, so I would suggest that you carefully check your code.

  18. Pingback: Button customization | Undocumented Matlab

  19. Christy says:

    Hey Mr. Altman,
    i have a question. I do create objects on the living program. That means for example i have uitabs and with every new uitab i add i add an editbox. Now on the first two editboxes i have “javahandle_withcallbacks.com.mathworks.hg.peer.utils.UIScrollPane” directly but on the third box i get a 1-by-4 handle. How can i ask which one is the one i need?
    regards

  20. Pingback: checkClass | Undocumented Matlab

  21. Pingback: Matlab GUI: Numeric input for serious work | Notes

  22. Kathi says:

    Dear Yair,
    I have a question concerning invisible figures. As you already explained (to Daniel, January 2010),
    findjobj will not find any underlying jaya components while the figure is still invisible.

    However, I have a GUIDE created GUI and I need to call it, telling him to stay invisible: MyGUI(‘Visible’,'off’)

    Naturally, I get a warning:
    Warning: No Java reference was found for the requested handle, because
    the figure is still invisible in MyGUI_OutputFcn()

    Is there a way to find the java while the figure is still invisible?
    Moreover, the code is working: I got a sortable table with single row selection.

    Thank you very much,
    And thank you for your wonderful web site.

    Best regards,
    Kathi

  23. Mohsen says:

    Hi Yair,

    I’ve used findjobj to align the row headers in my uitable. The problem is when I try to change the dimension of my table it does not allow the new row names to be visible.
    for example, if I want to increase the row numbers from 5 to 10, the last 5 rows do not get visible!

    Regards,
    Mohsen

  24. Sergey Kucheryavskiy says:

    Dear Yair,

    I am trying to get GUI layout toolbox (http://www.mathworks.com/matlabcentral/fileexchange/27758-gui-layout-toolbox) working with the new HG2 system, which will be default from 2014b. The toolbox uses property “PixelBounds” as an indicator that size of container has been changed. And there is a trigger:

    obj.Listeners{end+1,1} = handle.listener( containerObj, findprop( containerObj, 'PixelBounds' ), ...
        'PropertyPostSet', @obj.onResized );

    I changed this to:

    obj.Listeners{end+1,1} = addlistener( containerObj, findprop(containerObj, 'PixelBounds'), 'PostSet', @obj.onResized );

    But then I realised that this property is not available in HG2. Can you please recommend a substitution for that? Thanks a lot in advance!

    • @Sergey – the GUI layout toolbox is incompatible with HG2 in several places, not just the one that you found. MathWorks is aware of this and I expect that they will update the FEX utility when 14b is finally released.

      Rather than using the GUI toolbox, you can use uiflowcontainer. By specifying non-inf WidthLimits and/or HeightLimits property values, you can fix the size/position automatically without needing a custom resize callback function.

    • Sergey Kucheryavskiy says:

      Yes, now I see it as well: — problems with Children in TabPanel and some others. Actually it was the TabPanel I decided to use the GUI layout, otherwise I feel quite comfortable with GridBagLayout you recommended in some go your post. Will find a workaround for now and wait for the fixes.

      Thanks!

  25. Niko says:

    Hi Yair,

    Thank you so much for this amazing code! It allowed me access so much more java-based functionality not available in matlab… One problem I’m seeing though, is that when I have multiple instances of the same figure window open, findjobj works for the first instance, but not the later opened ones. Am I not using the code correctly, or maybe there is a way to work around this?

    In the openingfcn of my figure:

    JEdit=findjobj(handles.MyEditBox);
    JEdit.Editable=0;

    And only the edit box in the first instance becomes in-editable.

    Thank you very much!

    Best,

    Niko

    • @Niko – findjobj should be places in the outputfcn() as I’ve explained in numerous places – it needs the figure window to be visible in order to find the Java components.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

<pre lang="matlab">
a = magic(3);
sum(a)
</pre>