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

Uicontrol callbacks

May 1, 2009 69 Comments

In my previous post I showed how we can extensively customize a Matlab uicontrol’s appearance and behavior by accessing its undocumented underlying Java object. In this post I will show how to further customize the control’s behavior using the callbacks exposed by its underlying object.
Matlab’s uicontrol handles normally expose only a few event callbacks. These are ‘CreateFcn’, ‘DeleteFcn’, ‘ButtonDownFcn’, ‘KeyPressFcn’ and the control-specific ‘Callback’. In contrast, the underlying Java control exposes many more callbacks: 26 standard callbacks, plus a few control-specific callbacks, as follows:

  • AncestorMovedCallback – fired when one of the component’s container ancestors has changed its position relative to its container.
  • AncestorAddedCallback – fired when one of the component’s container ancestors has been added to another container
  • AncestorRemovedCallback – fired when one of the component’s container ancestors has been removed from the component’s hierarchy
  • AncestorResizedCallback – fired when one of the component’s container ancestor has been resized
  • ComponentAddedCallback – fired when a sub-component is added as a direct child to this component. Compare: ComponentRemovedCallback
  • ComponentHiddenCallback – fired when the component is hidden (setVisible(false)). Compare: ComponentShownCallback
  • ComponentMovedCallback – fired when the component is moved within its container. Since Java components are enclosed in a tight-fitting HG container, this callback will never fire for them: it does not fire when the container moves or resizes, only when the component’s starting position is moved within it.
  • ComponentRemovedCallback – fired when a sub-component is added as a direct child to this component. Compare: ComponentAddedCallback
  • ComponentResizedCallback – fired when the component is resized, either directly or because its container was resized.
  • ComponentShownCallback – fired when the component is displayed (setVisible(true)). Compare: ComponentHiddenCallback
  • FocusGainedCallback – fired when the component gains GUI focus, by mouse click, Tab click, or calling the component’s requestFocus() method.
  • FocusLostCallback – fired when the component loses focus to another component or window. Compare: FocusGainedCallback
  • HierarchyChangedCallback – fired when the component changes its ancestors (for example, moved from one panel to another).
  • KeyPressedCallback – fired continuously when any keyboard button (including Shift, Ctrl etc.) was pressed while the component had focus. The meta-data contains details about the specific key and modifiers (Alt, Shift, Ctrl, …) that were pressed. Compare: KeyReleasedCallback, KeyTypedCallback
  • KeyReleasedCallback – fired when a keyboard button was released while the component had focus. The meta-data contains details about the specific key and modifiers (Alt, Shift, Ctrl, …) that were pressed. Compare: KeyPressedCallback
  • KeyTypedCallback – similar to KeyPressedCallback, but only fired (continuously) when an actual printable character is clicked. Therefore, for Shift-A, KeyPressedCallback will fire twice (Shift, ‘A’) but KeyTypedCallback will only fire once. Compare: KeyPressedCallback, KeyReleasedCallback
  • MouseClickedCallback – fired when a mouse button is pressed and then released (=clicked) within the component’s bounds. If either the press or the release occurs outside the component’s bounds, the event will not fire. The figure’s ‘SelectionType’ property will be ‘normal’, ‘extend’ or ‘alt’ depending on which button was pressed. Compare: MousePressedCallback, MouseReleasedCallback.
  • MouseDraggedCallback – fired continuously when the mouse is clicked within the component’s bounds and then moved while the button is still depressed (i.e., dragged), even beyond the component’s bounds. The callback event’s meta-data will contain the delta-x and delta-y of the movement (positive for x-right/y-down; negative for x-left/y-up). Compare: MouseMovedCallback
  • MouseEnteredCallback – fired when the mouse is moved (depressed or not) into the component’s bounds. Compare: MouseExitedCallback
  • MouseExitedCallback – fired when the mouse is moved (depressed or not) out of the component’s bounds. Compare: MouseEnteredCallback
  • MouseMovedCallback – fired continuously when the mouse is moved undepressed within the component’s bounds. The callback event’s meta-data will contain the delta-x and delta-y of the movement (positive for x-right/y-down; negative for x-left/y-up). Compare: MouseDraggedCallback
  • MousePressedCallback – fired immediately when the mouse button is depressed (even before it was released) within the component’s bounds. The callback event’s meta-data will contain the click location within the component’s bounds. Compare: MouseClickedCallback, MouseReleasedCallback
  • MouseReleasedCallback – fired immediately when the mouse button is released within the component’s bounds. The callback event’s meta-data will contain the click location within the component’s bounds. Compare: MousePressedCallback
  • MouseWheelMovedCallback – fired immediately when the mouse wheel is turned (even before it was released) within the component’s bounds.
  • PropertyChangeCallback – fired when one of the component’s properties has changed. For example, after setting the component’s text, tooltip or border. Does not fire when modifying the component’s callback properties.
  • VetoableChangeCallback – fired upon a constrained property value change, allowing the callback to intercept and prevent the property change by raising an exception. Of all the Swing components, only JInternalFrame actually declares vetoable properties which can be intercepted.

It should be noted that these callbacks are standard in all Swing GUI controls. Thus, they can be used not just for Matlab uicontrols’ underlying Java objects, but also for any Swing component that you display using Matlab’s built-in javacomponent function.
The specific list of callbacks supported by each component depends on component type. As noted above, some components have additional specific callbacks. For example, ActionPerformedCallback is fired when a user has performed the main action associated with the control (selecting/clicking etc.). This is one of the most commonly used callbacks, one of the few exposed by Matlab HG handles (as the general-purpose ‘Callback’). This callback is implemented by JButton and JCheckBox (for instance), but not by JList or JMenu. CaretUpdateCallback and CaretPositionChangedCallback are only supported by text-entry controls like JTextField or JEditorPane, but not by JSlider or JTabbedPane. Other components have other such specific callbacks.
To see the full list of supported callbacks for a particular object, use the UIINSPECT utility from the File Exchange or use the following code snippet:

>> props = sort(fieldnames(get(javax.swing.JButton)));
>> callbackNames = props(~cellfun(@isempty,regexp(props,'Callback$')));
callbackNames =
    'ActionPerformedCallback'
    'AncestorAddedCallback'
    'AncestorMovedCallback'
    ...

A nice example of using Java callbacks to automatically select (highlight) the content text in a text-box when focus is gained was one of the first online posts in CSSM to use Matlab 7’s new javacomponent Swing integration.
Another typical usage is to set a continuously-firing callback whenever a slider uicontrol is dragged – the Matlab HG callback only fires once after the drag has completed, whereas we often wish to update some value or graphics during the drag events. This can easily be done using JSlider’s underlying object (a Swing JScrollBar) callbacks.

In order to prevent memory leaks in heavily-laden GUIs, it is advisable to get and set callback properties using the handle object, instead of directly on the “naked” Java reference. For this reason, using set/get is discouraged by MathWorks and may even be disabled in some future Matlab release:

jb = javax.swing.JButton;
jbh = handle(jb,'CallbackProperties');
% or for an existing uicontrol: jbh = findjobj(hButton);
set(jbh, 'ActionPerformedCallback',@myCallbackFcn)  % ok!
set(jb,  'ActionPerformedCallback',@myCallbackFcn)  % bad! memory leak

In some future post I plan to present more details about handle() and its intricacies. But in a nutshell, this code snippet is all you need to start working.
Callbacks can be set in the normal Matlab fashion, using one of three methods:

set(jbh, 'ActionPerformedCallback',@myCallbackFcn);
set(jbh, 'ActionPerformedCallback',{@myCallbackFcn,param1,param2});
set(jbh, 'ActionPerformedCallback','disp(123);');

I would be happy to hear how you use these newly-exposed callbacks in your application. Please leave your welcome comments below.

Related posts:

  1. Matlab callbacks for Java events in R2014a – R2014a changed the way in which Java objects expose events as Matlab callbacks. ...
  2. uisplittool & uitogglesplittool callbacks – Matlab's undocumented uisplittool and uitogglesplittool are powerful toolbar controls - this article explains how to customize their behavior...
  3. Additional uicontrol tooltip hacks – Matlab's uicontrol tooltips have several limitations that can be overcome using the control's underlying Java object....
  4. Setting line position in an edit-box uicontrol – Matlab uicontrols have many useful features that are only available via Java. Here's how to access them....
  5. Customizing uicontrol border – Matlab uicontrol borders can easily be modified - this article shows how...
  6. Aligning uicontrol contents – Matlab uicontrols can often be customized using plain HTML/CSS, without need for advanced Java. ...
Callbacks FindJObj GUI Java uicontrol UIInspect
Print Print
« Previous
Next »
69 Responses
  1. sleesh May 5, 2009 at 13:00 Reply

    Hi Yair.

    I would just like to leave you a note, that I am always impressed by your comments, notes and posts on comp.soft-sys.matlab or TMW file-exchange.

    Seems as if you now decided to publish some deeper insights to the matter – great work!

    Since you asked for some input what people are interested in – my 2-cents:
    1. How to disable/enable single nodes of uitree?
    2. How to set the background color of the uitable, a single row, a single column (possible in 2008a and later, but impossible for me in 2007b)?

    • Yair Altman May 6, 2009 at 12:27 Reply

      Thanks Sleesh.

      1. try setting the ‘enable’ property of the nodes

      2. in the old uitable, there are several ways to set the background color:
      a) Use each column’s cell renderer:

      cr = javax.swing.table.DefaultTableCellRenderer;
      cr.setForeground(java.awt.Color.red);
      cr.setBackground(java.awt.Color(0.2,0.3,0.8)); %dark-blue
      jtable.getColumnModel.getColumn(1).setCellRenderer(cr); % 0=first column; 1=second column; …

      b) use HTML data in the table: <html><font color=”red”>123.456 … – this is good for read-only cells but not good for editable cells because when you edit the cell you’ll see the HTML code…

      There is no easy way to set row colors – either set HTML colors programmatically or create a custom TableCellRenderer Java class

      Yair

  2. junziyang May 15, 2009 at 18:57 Reply

    Is there anyway to wrap a JAVA component into a MATALB handle? I mean to retrun a matlab-like handle(a number) to the user after the creation of the Java component in MATLAB. While, only part of the properties of the JAVA object can be accessed through the handle.
    thanks.

    • Yair Altman May 16, 2009 at 10:34 Reply

      @Junziyang – when creating a component you get a handle to the Java object that you can then use in Matlab using the built-in get/set functions etc. However, to prevent all sorts of issues (memory leaks, inaccessible callbacks etc.), you should normally use the returned object within a Matlab handle(), like so:

      javaObj = JavaClass(constructor_params);
      objHandle = handle(javaObj,’CallbackProperties’);
      % from now on, use get(objHandle,…) or set(objHandle,…) or objHandle.method()

      Yair

  3. EditorMacro - assign a keyboard macro in the Matlab editor | Undocumented Matlab July 1, 2009 at 12:18 Reply

    […] EditorMacro is a new utility that enables setting keyboard macros in the Matlab editor. In a nutshell, EditorMacro sets the KeyPressedCallback property (explained in a previous post) for each of the editor’s document panes, to an internal function. […]

  4. Setting listbox mouse actions | Undocumented Matlab August 13, 2009 at 15:31 Reply

    […] Matlab listbox uicontrol can be modified to detect mouse events for right-click context menus, dynamic tooltips etc. […]

  5. Detecting window focus events | Undocumented Matlab September 9, 2009 at 13:50 Reply

    […] The list of standard Swing callbacks was detailed in my earlier article about uicontrol callbacks, which is also relevant for Java windows […]

  6. Continuous slider callback | Undocumented Matlab February 8, 2010 at 02:13 Reply

    […] explained in an earlier article, Matlab uicontrols are basically Java Swing objects that possess a large number of useful callbacks […]

  7. Yair Altman March 9, 2010 at 02:32 Reply

    In answer to a CSSM question asking for an explanation of the memory leak problem when setting Matlab callbacks directly on the Java object (rather than on their handle), there is an official MathWorks post on this.

    Also see the following related CSSM threads here and here.

  8. JIDE Property Grids | Undocumented Matlab April 21, 2010 at 23:02 Reply

    […] Just as with any Java object, these fields may either be accessed with the Java get/set semantics (e.g. getName() or setName(name)), or the Matlab get/set semantics (e.g. get(prop,’Name’) or set(prop,’Name’,name)). When using the Matlab syntax, remember to wrap the Java object in a handle() call, to prevent a memory leak. […]

  9. iroln November 4, 2010 at 09:05 Reply

    I want to use mouse uicontrol callbacks, but they don’t work. 🙁
    Here’s what I’m doing:

    function TestMouseCallbacks()
        hFig = figure();
        warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame');
        drawnow;
        jh = get(hFig, 'JavaFrame');
        jf = jh.fFigureClient.getWindow;
        jbh = handle(jf, 'CallbackProperties');
        set(jbh, 'MouseWheelMovedCallback', {@MousePressed})
    end
     
    function MousePressed(~, ~)
        disp('Pressed')
    end

    function TestMouseCallbacks() hFig = figure(); warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); drawnow; jh = get(hFig, 'JavaFrame'); jf = jh.fFigureClient.getWindow; jbh = handle(jf, 'CallbackProperties'); set(jbh, 'MouseWheelMovedCallback', {@MousePressed}) end function MousePressed(~, ~) disp('Pressed') end

    This code does not respond to mouse events (mouse events can be any).
    I also noticed that the keyboard events do not work and some other events.

    • Donn Shull November 4, 2010 at 10:18 Reply

      @iroln Try placing your mouse over the title bar of your figure and then turning the mouse wheel.

      Donn

      • iroln November 4, 2010 at 10:47

        @Donn Shull, I tried to do it. Mouse events are not working. “MousePressedCallback”, “MouseReleasedCallback”, “MouseMovedCallback” etc… None of them works.
        The problem is that I want use the MATLAB figure for high-performance display very big images, using HWND (Matlab graphics subsystem is very weak) . Сlasses to render images written in C++. I need to get this to work in Matlab. But I know bad java gui toolkits. Therefore have difficulty in understanding the bundles of Matlab-Java.

      • Donn Shull November 4, 2010 at 16:01

        @iroln – When I tried your code it only recognized the the mouse and issued the callback when the mouse was over the window title area that is the area where it says Figure 1. The callbacks are not issued for any other area of the figure.

      • iroln November 4, 2010 at 23:58

        @Donn Shull, I use Windows 7 x64 and MATLAB R2010b x64. What configuration do you use?

        At first I thought that to origin of events of the mouse hinders PanelContainer (Its events are working properly). For check I have written such code:

        jhp = get(jh, 'FigurePanelContainer');
        jhp.setSize(100, 100)

        jhp = get(jh, 'FigurePanelContainer'); jhp.setSize(100, 100)

        But it didn’t help 🙂

        The following Callback works only within that PanelContainer:

        set(hFig, 'WindowButtonDownFcn', {@MousePressed})

        set(hFig, 'WindowButtonDownFcn', {@MousePressed})

      • Donn Shull November 5, 2010 at 08:53

        @iroln – I am using windows 7 32 bit and the code you just sent works as you described

    • Yair Altman November 7, 2010 at 15:40 Reply

      @iroln and Donn – apparently all mouse actions are delegated to the AxisCanvas component, so simply set your callback on that component. It works for me on R2010b. Here’s the complete code snippet:

      function TestMouseCallbacks()
        hFig = figure();
        warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame');
        drawnow;
        jh = get(hFig, 'JavaFrame');
        jf = jh.fFigureClient.getAxisComponent;  % note the change
        jbh = handle(jf, 'CallbackProperties');
        set(jbh, 'MouseWheelMovedCallback', @MousePressed)
      end
       
      function MousePressed(jObject, jEventData)
        disp('Pressed')
      end

      function TestMouseCallbacks() hFig = figure(); warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); drawnow; jh = get(hFig, 'JavaFrame'); jf = jh.fFigureClient.getAxisComponent; % note the change jbh = handle(jf, 'CallbackProperties'); set(jbh, 'MouseWheelMovedCallback', @MousePressed) end function MousePressed(jObject, jEventData) disp('Pressed') end

      • iroln November 10, 2010 at 14:11

        Thanks, Yair Altman!

  10. Sean Larkin December 7, 2010 at 12:12 Reply

    I’m trying to use findjobj to get the java handle for a toolbar uitogglebutton. It does not find the handles for the button. When I call the function like this:
    findjobj;

    it finds the toolbar button. Why is this and is there a way I can modify findjobj to directly find toolbar buttons?

    • Yair Altman December 7, 2010 at 12:59 Reply

      @Sean – take a look at: http://undocumentedmatlab.com/blog/modifying-default-toolbar-menubar-actions/

      Related articles:
      http://undocumentedmatlab.com/blog/figure-toolbar-components/
      http://undocumentedmatlab.com/blog/figure-toolbar-customizations/

      – Yair

  11. Janos Marki January 30, 2011 at 05:12 Reply

    Hi,

    I have a problem that I can’t seem to solve, and I can’t find the info.

    I execute a number of commands culminating in a plot. At this point, I need to intervene manually, which I thought of doing via the WindowKeyPressFcn callback of the figure I plotted in. Once done, I would like script execution to resume.

    However, whatever way I use to stop keyboard execution (keyboard, waitfor(figHand), no matter what I do, instead of the figure’s callback (scalSet.m) activating, the pressed key appears in the command window (i.e. I cannot make the figure the “active” object so the pressed key goes into it). It seems to me like this goes against the notion of having ready code, running the GUI, and then interacting with it (as interaction would already start whilst the script is run). Is this me trying to use Matlab in ways it has not been intended to work? Can it be done, or should I just do it differently?

    a111=figure('WindowKeyPressFcn',@scalSet); 
    waitfor(a111,'UserData','Done');

    a111=figure('WindowKeyPressFcn',@scalSet); waitfor(a111,'UserData','Done');

    …and the idea was to have one key (d) for the “Done” state in the callback function (waitfor would let the script carry on once this is triggered), which looks like this:

    function scalSet(src,eventdata)
    %function scalSet(src,eventdata)
    %
    %Function used to set scales with the mouse manually on plots with a colorbar
    %Press 'r' to narrow the scale by clicking two values on the
    %colorbar with the mouse
    %
    %Press 'w' to double the range
    %
    %enter set(gcf,'WindowKeyPressFcn',@scalSet) to add it to figures a
    %posteriori
     
    %we want to make the colorbar scaling smaller
    if strcmp(eventdata.Character,'r')
       scval=ginput(2);
       chs=get(src,'Children');
       for k=1:length(chs)
           nu=get(chs(k),'Type');
           if strcmp(nu,'axes')
             nu2=get(chs(k),'Tag');
               if ~strcmp(nu2,'Colorbar')
                   caxis(chs(k),[sort(scval(:,2))'])
               end
           end
       end   
    end
     
    %we want to widen it
    if strcmp(eventdata.Character,'w')
       scval=caxis;
       wid=scval(2)-scval(1);
       caxis([scval(1)-wid scval(2)+wid])
    end
     
    %we are done
    if strcmp(eventdata.Character,'d')
       set(src,'UserData','Done') 
    end

    function scalSet(src,eventdata) %function scalSet(src,eventdata) % %Function used to set scales with the mouse manually on plots with a colorbar %Press 'r' to narrow the scale by clicking two values on the %colorbar with the mouse % %Press 'w' to double the range % %enter set(gcf,'WindowKeyPressFcn',@scalSet) to add it to figures a %posteriori %we want to make the colorbar scaling smaller if strcmp(eventdata.Character,'r') scval=ginput(2); chs=get(src,'Children'); for k=1:length(chs) nu=get(chs(k),'Type'); if strcmp(nu,'axes') nu2=get(chs(k),'Tag'); if ~strcmp(nu2,'Colorbar') caxis(chs(k),[sort(scval(:,2))']) end end end end %we want to widen it if strcmp(eventdata.Character,'w') scval=caxis; wid=scval(2)-scval(1); caxis([scval(1)-wid scval(2)+wid]) end %we are done if strcmp(eventdata.Character,'d') set(src,'UserData','Done') end

    Thanks!
    Janos

    • Janos Marki January 30, 2011 at 07:27 Reply

      Update to previous: it now works. I think the problem was with the callback getting overwritten for some reason (only possible culprit: pcolor function). By inserting the callback handle again, it works without a hitch. Sorry for the hassle.

      Janos

      figure(a111)
      set(gcf,'WindowKeyPressFcn',@scalSet)
      waitfor(a111,'UserData','Done');

      figure(a111) set(gcf,'WindowKeyPressFcn',@scalSet) waitfor(a111,'UserData','Done');

  12. Dave January 3, 2012 at 08:35 Reply

    Yair, your knowledge is incredible, thank you for sharing.
    Please excuse my lack of understanding but it seems that whenever I try to use a callback it sends javahandle_withcallbacks.com.mathworks.mwswing.MJButton as the first parameter.

    function badprogrammingpractice
     
    hFig = figure('position', [300 300 600 400]);
    jbt = com.mathworks.mwswing.MJButton('click me');
    jbt.setBorder([])
    jbt.setBackground(java.awt.Color.white);
    jbt.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.HAND_CURSOR));
    jbt.setFlyOverAppearance(1);
    bob = [1 2 3]
    jbtPosition = [0.1 0.1 0.3 0.3]
    [dummy,btContainer] = javacomponent(jbt,[0 0 1 1],hFig);
    set(btContainer, 'Units','Norm', 'Position',jbtPosition);
    hbt = handle(jbt,'CallbackProperties');
    set(hbt,'ActionPerformedCallback',@dosomething);
     
    function [mean,stdev] = dosomething(x,y)
    x

    function badprogrammingpractice hFig = figure('position', [300 300 600 400]); jbt = com.mathworks.mwswing.MJButton('click me'); jbt.setBorder([]) jbt.setBackground(java.awt.Color.white); jbt.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.HAND_CURSOR)); jbt.setFlyOverAppearance(1); bob = [1 2 3] jbtPosition = [0.1 0.1 0.3 0.3] [dummy,btContainer] = javacomponent(jbt,[0 0 1 1],hFig); set(btContainer, 'Units','Norm', 'Position',jbtPosition); hbt = handle(jbt,'CallbackProperties'); set(hbt,'ActionPerformedCallback',@dosomething); function [mean,stdev] = dosomething(x,y) x

    output:

    bob =
    1 2 3
    jbtPosition =
    0.1000 0.1000 0.3000 0.3000
    x =
    javahandle_withcallbacks.com.mathworks.mwswing.MJButton
    >>

    • Yair Altman January 5, 2012 at 03:05 Reply

      @Dave – this is correct. Matlab callbacks always send the originating object (in your case, a button which is actually an MJButton control) as the first parameter, and an eventData object as the second parameter. in eventData you can find information regarding the event, for example whether the button was clicked or right-clicked etc.

  13. Matlab-Java memory leaks, performance | Undocumented Matlab January 20, 2012 at 04:52 Reply

    […] a Matlab callback that gets invoked multiple times per second by a Java object (see related articles here and here). Each time the Matlab callback function is invoked, it reads the event information […]

  14. Keith March 2, 2012 at 18:24 Reply

    I’ve got a uicontrol popup menu (not shown below) and an edit uicontrol (shown here) the default text on the edit text box is ‘User Types Text Here’ I want this to disappear (set the string to []) whenever the user clicks on the edit text box, and reappear (set the string to the default text) if they deselect (by clicking something else) the textbox and the string is still []. Also I want the strings on two push buttons (accept and discard) to change appropriately (for example their string=’ ‘ if the string of the edit text box is the default string or empty and display ‘Accept text’ and ‘Discard text’, there’s also ‘Accept file’ and ‘Discard file’ strings depending whether a ‘fill with…’ popup menu is set to ‘fill with text’ or ‘fill with file’ and there are a few other options too) some code fragments are below

    the problem I was having was that PostSet listeners of the uicontrols ‘Selected’ property aren’t triggering and my attempt to use the java (via your findjobj function aren’t working either) maybe I’m doing it wrong
    changes to the string of the edit text box aren’t triggering PostSet listeners either (at least not until I click somewhere other than the editable text box, which is too late, I want the label of the accept discard buttons to appear before they click somewhere else)

    Can you help me?

    Thanks,

    Keith

    function make_user_text(hSynLowerLeftPanel,UserTextPos,WXWYInches,...
        usertextstate)
        SYNUD=getSynopsisUserData();
        GUIFont=SYNUD.Preferences.GUIFont;
        UserEditBackColor=SYNUD.UserEdit.Color.Back;
     
        WYButtonNorm=min(0.3/WXWYInches(2),UserTextPos(4)/3);
        UserTextPos(4)=UserTextPos(4)-WYButtonNorm;
        UTUD.DefaultString='User Types Text Here';
        hUserText=uicontrol('Parent',hSynLowerLeftPanel,'style','edit',...
            'units','normalized','position',UserTextPos,...
            'Tag','SynopsisUserText','Min',1,'Max',1000,...
            'FontName',GUIFont.Name,'FontSize',GUIFont.Size,...
            'BackgroundColor',UserEditBackColor);    
        jUserText=findjobj(hUserText)
        jUserText.FocusGainedCallback=@userTextSelectCallback;
        jUserText.FocusLostCallback=@userTextDeselectCallback;
     
        UTUD.hhUserText=handle(hUserText)
        UTUD.hUserTextString=findprop(UTUD.hhUserText,'String');
        UTUD.hListenUserTextString=handle.listener(UTUD.hhUserText,...
            UTUD.hUserTextString,'PropertyPostSet',...
            'listenerCallbackToSetAcceptDiscardLabels()');
        set(hUserText,'UserData',UTUD);
    ....
    end
     
    function userTextSelectCallback()
        %this needs to trigger whenever the user selects the user text box (an 
        %edit uicontrol)
        disp('userTextSelectCallback()');
        hUserText=findobj('Tag','SynopsisUserText');
        userTextString=get(hUserText,'String');
        UTUD=get(hUserText,'UserData');    
        if(strcmpi(userTextString,UTUD.DefaultString))
            %if/when you select the userText box and it has the default string
            %("User Types Text Here") then this removes the default string 
            %so the user doesn't have to backspace it away
            set(hUserText,'String',[]);
            userTextString=[];
        end
    end
     
    function userTextDeselectCallback()
        %this needs to trigger whenever the user deselects the user text box 
        %(an edit uicontrol)
        disp('userTextDeselectCallback()');
        hUserText=findobj('Tag','SynopsisUserText');
        userTextString=get(hUserText,'String');
        UTUD=get(hUserText,'UserData');
        if(isempty(userTextString))        
            %if/when you unselect (click anything else) user edit text box and
            %the user edit text box string is empty then this resets the string
            %to the default "User Types Text Here" String
            set(hUserText,'String',UTUD.DefaultString);
        end
    end
     
     
    function listenerCallbackToSetAcceptDiscardLabels()
        %this function assigns the appropriate labels to the 'Accept ...' and
        %'Discard ...' pushbuttons, where appropriate means:
        %' ' if the user text box isn't supposed to be receiving instructions
        %  OR
        %'... text' if the 'fill with ...' popupmenu is set to 'fill with text'
        %  OR
        %'... file' if the 'fill with ...' popupmenu is set to 'fill with file'
     
        hUserText=findobj('Tag','SynopsisUserText');
        userTextString=get(hUserText,'String');
        UTUD=get(hUserText,'UserData');
        hAcceptTextOrFilePush=findobj('Tag','SynopsisAcceptTextFilePush');
        hDiscardTextOrFilePush=findobj('Tag','SynopsisDiscardTextFilePush');
        if(isempty(userTextString)||strcmpi(userTextString,UTUD.DefaultString))
            set(hAcceptTextOrFilePush,'String',' ');
            set(hDiscardTextOrFilePush,'String',' ');
        else
            disp('listenerCallbackToSetAcceptDiscardLabels')
            hFillWithPopup=findobj('Tag','SynopsisFillWithPopup');
            FWUD=get(hFillWithPopup,'UserData');
            fwvalue=get(hFillWithPopup,'value')
            fwstring=get(hFillWithPopup,'string')
            fwstring=fwstring{fwvalue};
            if(strcmpi(fwstring,FWUD.String{2}))
                %fill with text so set the accept button to 'accept text',
                %and the discard button to 'discard text'
                ATFUD=get(hAcceptTextOrFilePush,'UserData');
                set(hAcceptTextOrFilePush,'String',ATFUD.String{1});
                DTFUD=get(hDiscardTextOrFilePush,'UserData');
                set(hDiscardTextOrFilePush,'String',DTFUD.String{1});                
            elseif(strcmpi(fwstring,FWUD.String{3}))
                %fill with file so set the accept button to 'accept file',
                %and the discard button to 'discard file'
                ATFUD=get(hAcceptTextOrFilePush,'UserData');
                set(hAcceptTextOrFilePush,'String',ATFUD.String{2});
                DTFUD=get(hDiscardTextOrFilePush,'UserData');
                set(hDiscardTextOrFilePush,'String',DTFUD.String{2});                                
            else
                %fill with ... or ' '
                set(hAcceptTextOrFilePush,'String',' ');
                set(hDiscardTextOrFilePush,'String',' ');
            end
        end
    end

    function make_user_text(hSynLowerLeftPanel,UserTextPos,WXWYInches,... usertextstate) SYNUD=getSynopsisUserData(); GUIFont=SYNUD.Preferences.GUIFont; UserEditBackColor=SYNUD.UserEdit.Color.Back; WYButtonNorm=min(0.3/WXWYInches(2),UserTextPos(4)/3); UserTextPos(4)=UserTextPos(4)-WYButtonNorm; UTUD.DefaultString='User Types Text Here'; hUserText=uicontrol('Parent',hSynLowerLeftPanel,'style','edit',... 'units','normalized','position',UserTextPos,... 'Tag','SynopsisUserText','Min',1,'Max',1000,... 'FontName',GUIFont.Name,'FontSize',GUIFont.Size,... 'BackgroundColor',UserEditBackColor); jUserText=findjobj(hUserText) jUserText.FocusGainedCallback=@userTextSelectCallback; jUserText.FocusLostCallback=@userTextDeselectCallback; UTUD.hhUserText=handle(hUserText) UTUD.hUserTextString=findprop(UTUD.hhUserText,'String'); UTUD.hListenUserTextString=handle.listener(UTUD.hhUserText,... UTUD.hUserTextString,'PropertyPostSet',... 'listenerCallbackToSetAcceptDiscardLabels()'); set(hUserText,'UserData',UTUD); .... end function userTextSelectCallback() %this needs to trigger whenever the user selects the user text box (an %edit uicontrol) disp('userTextSelectCallback()'); hUserText=findobj('Tag','SynopsisUserText'); userTextString=get(hUserText,'String'); UTUD=get(hUserText,'UserData'); if(strcmpi(userTextString,UTUD.DefaultString)) %if/when you select the userText box and it has the default string %("User Types Text Here") then this removes the default string %so the user doesn't have to backspace it away set(hUserText,'String',[]); userTextString=[]; end end function userTextDeselectCallback() %this needs to trigger whenever the user deselects the user text box %(an edit uicontrol) disp('userTextDeselectCallback()'); hUserText=findobj('Tag','SynopsisUserText'); userTextString=get(hUserText,'String'); UTUD=get(hUserText,'UserData'); if(isempty(userTextString)) %if/when you unselect (click anything else) user edit text box and %the user edit text box string is empty then this resets the string %to the default "User Types Text Here" String set(hUserText,'String',UTUD.DefaultString); end end function listenerCallbackToSetAcceptDiscardLabels() %this function assigns the appropriate labels to the 'Accept ...' and %'Discard ...' pushbuttons, where appropriate means: %' ' if the user text box isn't supposed to be receiving instructions % OR %'... text' if the 'fill with ...' popupmenu is set to 'fill with text' % OR %'... file' if the 'fill with ...' popupmenu is set to 'fill with file' hUserText=findobj('Tag','SynopsisUserText'); userTextString=get(hUserText,'String'); UTUD=get(hUserText,'UserData'); hAcceptTextOrFilePush=findobj('Tag','SynopsisAcceptTextFilePush'); hDiscardTextOrFilePush=findobj('Tag','SynopsisDiscardTextFilePush'); if(isempty(userTextString)||strcmpi(userTextString,UTUD.DefaultString)) set(hAcceptTextOrFilePush,'String',' '); set(hDiscardTextOrFilePush,'String',' '); else disp('listenerCallbackToSetAcceptDiscardLabels') hFillWithPopup=findobj('Tag','SynopsisFillWithPopup'); FWUD=get(hFillWithPopup,'UserData'); fwvalue=get(hFillWithPopup,'value') fwstring=get(hFillWithPopup,'string') fwstring=fwstring{fwvalue}; if(strcmpi(fwstring,FWUD.String{2})) %fill with text so set the accept button to 'accept text', %and the discard button to 'discard text' ATFUD=get(hAcceptTextOrFilePush,'UserData'); set(hAcceptTextOrFilePush,'String',ATFUD.String{1}); DTFUD=get(hDiscardTextOrFilePush,'UserData'); set(hDiscardTextOrFilePush,'String',DTFUD.String{1}); elseif(strcmpi(fwstring,FWUD.String{3})) %fill with file so set the accept button to 'accept file', %and the discard button to 'discard file' ATFUD=get(hAcceptTextOrFilePush,'UserData'); set(hAcceptTextOrFilePush,'String',ATFUD.String{2}); DTFUD=get(hDiscardTextOrFilePush,'UserData'); set(hDiscardTextOrFilePush,'String',DTFUD.String{2}); else %fill with ... or ' ' set(hAcceptTextOrFilePush,'String',' '); set(hDiscardTextOrFilePush,'String',' '); end end end

  15. Oscar September 7, 2012 at 08:53 Reply

    First of all, I would like to thank you for sharing your amazing knowledge.

    My problem is I’d like to execute a callback function when any key combination is pressed inside Matlab. I don’t know what object’s property I should modify. I basically want it to behave the same way it does when you press the combination CTRL+C but performing an specific action.

    Is there any way to do that?

    Thanks!

    • Yair Altman September 8, 2012 at 10:49 Reply

      @Oscar – take a look at the figure’s KeyPressFcn property

  16. uiinspect | Undocumented Matlab January 23, 2013 at 11:01 Reply

    […] A checkbox next to the table’s toolbar enables hiding standard Java Swing callbacks. This is important when we inspect Java controls and only wish to see its unique callbacks. […]

  17. Vladimir February 28, 2013 at 08:42 Reply

    I have a memory leak kind of problem.
    I’m creating a jLabel object which is wrapped in the MATLAB class.
    I’m using the handle for all sets/gets to try prevent problems and memory leaks.

    I’m setting the MouseExitedCallback for jLabel using this code. It’s a method of the class:

        function SetMouseExitedCallback (obj, exitcallback)
            set (obj.hLabel, 'MouseExitedCallback', exitcallback)
        end

    function SetMouseExitedCallback (obj, exitcallback) set (obj.hLabel, 'MouseExitedCallback', exitcallback) end

    This method is called from another class which actually contains the code for MouseExitedCallback.
    In that class it is called like this:

    obj.tooltip.SetMouseExitedCallback (@(src, event)obj.MouseExited);

    obj.tooltip.SetMouseExitedCallback (@(src, event)obj.MouseExited);

    The problem that I’m getting is if I add this last line, if I try to edit files in the project it tells me that jLabel class is still in the memory.
    What can I do to prevent this?

    Vladimir

    • Malcolm Lidierth February 28, 2013 at 08:53 Reply

      Try setting ‘MouseExitedCallback’ empty before destroying the object e.g. in a delete method.

    • Vladimir March 1, 2013 at 00:56 Reply

      Yes, that was my thought also, but putting it in the delete (destructor) method didn’t work because destructor was never being called. Actually destructor was never called for another class also, the one where actual MouseExited() callback was defined.

      What worked at the end is to call:

      obj.tooltip.SetMouseExitedCallback ('');

      obj.tooltip.SetMouseExitedCallback ('');

      in the the method which is hiding the tooltip.

      Then after the application is closed VM calls destructors and destroy the object.

      • Malcolm Lidierth March 2, 2013 at 04:35

        @Vladimir
        OK. Looks like the leaked reference means delete is not called.

        I encountered something like this with the Waterloo Swing Library objects. It seems circular references to objects can result in leaks so that a call to obj.delete() seems to work but referencing obj in the delete method throws an error because obj.isValid returns false. This was difficult to debug but trial-and-error provided a general solution that seems to work:

        The GTool superclass in Waterloo has some methods do deal with this, see here.
        Essentially the superclass provides an onCleanup method to be called from subclass constructors. That keeps a table of objects in the application data area of the MATLAB container being used. A delete callback on the MATLAB container removes all callback references to custom-objects in the table during deletion of the MATLAB container, and calls the custom-object’s delete method. GTool contains a static method, cleanupContainer to do that which targets only those callbacks I use.

        There has been some discussion about this on MATLAB Answers.

        My guess is this is the delete equivalent of referencing “this” during its construction in e.g. Java. For HG objects there is a BeingDeleted property.

  18. Sebastian K. April 14, 2013 at 12:42 Reply

    Hey Yair,

    first of all: thank you very much for your effort presenting all – well probably ‘some of’ fits better here 😉 – your knowledge here in your blog as well as in your Book (I purchased it 2 weeks ago).

    Unfortunately, I got stuck with Callbacks of Figure Windows – since the whole GUI Container Hierarchy confuses me. What I want to do: fire a callback, when the title bar of a Figure Window is clicked e.g. to move the Figure Window. I can’t find the right place to put the callback function. Here’s a simple code snippet in which a callback is fired when the mouse is clicked anywhere in the contentPane… but that is not what I want. I would be pleased, if you could help me out. My Matlab Version: R2012b.

    function setWindowCallback( )
        % plot some data
        h = figure();
        plot(1:10);
        % get JavaFrame
        jf  = get(h, 'JavaFrame')
        % get JavaFrame by means of Yair's getjframe function
        jf2 = getjframe(h)
    	% get handle
        hf   = handle(jf.fHG1Client.getAxisComponent, 'CallbackProperties')
        %	get handle
        hf2  = handle(jf2, 'CallbackProperties')
        % set callback for action within ContentPane
        set(hf, 'MouseClickedCallback', @testAction)
        % set callback for entire Figure ( DOES NOT WORK :( )
        set(hf2, 'MouseClickedCallback', @testAction)
    end
     
    function testAction(jObject, jEvntData)
        display('Hello World')
    end

    function setWindowCallback( ) % plot some data h = figure(); plot(1:10); % get JavaFrame jf = get(h, 'JavaFrame') % get JavaFrame by means of Yair's getjframe function jf2 = getjframe(h) % get handle hf = handle(jf.fHG1Client.getAxisComponent, 'CallbackProperties') % get handle hf2 = handle(jf2, 'CallbackProperties') % set callback for action within ContentPane set(hf, 'MouseClickedCallback', @testAction) % set callback for entire Figure ( DOES NOT WORK :( ) set(hf2, 'MouseClickedCallback', @testAction) end function testAction(jObject, jEvntData) display('Hello World') end

    • Yair Altman April 14, 2013 at 14:01 Reply

      @Sebastian – thanks. Why not simply try placing a UDD listener on the figure’s Position property?

    • Malcolm Lidierth April 14, 2013 at 15:35 Reply

      Yair’s answer is the simplest route. If you need Java you need, a component listener, not mouse because the mouse events are not in the content pane, as you say, and are absorbed by the title bar handlers. You can derive mouse position in the component listener (but working with mouse positions relative to a window being moved by the mouse can get tricky). For a component moved callback:

      >> temp = javaframe.getFigurePanelContainer();
      >> target = javax.swing.SwingUtilities.getRoot(temp);
      >> handle(target,'callbackproperties')
      ans =
      	javahandle_withcallbacks.com.mathworks.hg.peer.FigureFrameProxy$FigureFrame
       
      >> set(h, 'ComponentMovedCallback', 'disp(99)')

      >> temp = javaframe.getFigurePanelContainer(); >> target = javax.swing.SwingUtilities.getRoot(temp); >> handle(target,'callbackproperties') ans = javahandle_withcallbacks.com.mathworks.hg.peer.FigureFrameProxy$FigureFrame >> set(h, 'ComponentMovedCallback', 'disp(99)')

    • Sebastian K. April 14, 2013 at 15:52 Reply

      @Yair: excellent solution! That was very easy – thanks, problem solved. Still I wonder why my first idea did not work…

      • Sebastian K. April 14, 2013 at 16:00

        @Malcom: thank you too… I have to think about that.

  19. Editbox data input validation | Undocumented Matlab October 2, 2013 at 10:09 Reply

    […] we have the jEditbox reference handle, we can use some ~30 different event callbacks that it exposes. Some of the useful callbacks […]

  20. Lauren October 7, 2013 at 10:49 Reply

    Yair,

    Thanks so much for taking the time to share your Matlab expertise! I was very excited to read this, as it seems to the best solution to a problem I would like to solve. However, I haven’t been able to implement this solution, and I’m not sure why it isn’t working for me.

    Specifically, I have some edit text boxes in a GUI, and I would like to trigger a callback whenever the text is altered (without necessarily waiting for the user to click outside the edit text box), and in the callback get the current state of the text so that I can adjust some other GUI components accordingly. My problem is that the standard “callback” function doesn’t trigger the callback function until you click outside the edit text box or press enter, and the “KeyPressFcn” triggers the callback function before the ‘String’ value for the edit text box has been updated. It seems that either “KeyReleasedCallback” or “PropertyChangedCallback” might solve my problem (i.e. trigger the callback after the ‘string’ property has been changed but without requiring “enter” or an extra click).

    I attempted to implement this in the following way, but it seems that the function is not getting triggered. There is not error message, so I’m not sure what I’m doing wrong.

    (h.editTextBox is an existing edit text box in my gui)

    jbh = findobj(h.editTextBox);
    set(jbh, 'KeyReleasedCallback', @callbackFcn)
    set(jbh, 'PropertyChangedCallback', @callbackFcn)

    jbh = findobj(h.editTextBox); set(jbh, 'KeyReleasedCallback', @callbackFcn) set(jbh, 'PropertyChangedCallback', @callbackFcn)

    Thanks for any help you can provide!

    • Yair Altman October 7, 2013 at 10:55 Reply

      @Lauren – my very recent article, that I have posted only a few days ago, discusses this issue exactly:
      http://undocumentedmatlab.com/blog/editbox-data-input-validation/

      Note that the article refers to single-line editboxes only – multi-line editboxes have somewhat different behavior, although the same general principles apply there as well.

      In your specific case, it is also possible that jbh returns empty for some reason, which could explain why the callbacks don’t get triggered.

  21. xay lee November 24, 2013 at 01:33 Reply

    Hi yair! i’m trying to make a piano in matlab, (it works perfectly if its Gui keys are pressed using mouse Click), i want to change that by using my keyboard keys (all A-Z and 0-9) so it should respond by clicking any key, i have tried to do it using key press function,but in vain, it would be great if you please tell me HOW TO DO IT by some example/code snippet related to keyboard keys func. THANKS 🙂
    one thing more my piano gui contains 80+ keys so is it possible to use combinations like shift+A etc as well

    • Yair Altman November 24, 2013 at 07:36 Reply

      @Lee – I suggest that you post your question on the CSSM newsgroup or the Matlab Answers forum.
      If you’d like my help on this as a professional consultant, please send me an offline email.

  22. Charlie December 28, 2013 at 09:35 Reply

    Hi Yair:

    Is it possible to assign these undocumented callbacks to a previously created figure (say figure(1))?

    Best regards,

    Charlie

    • Yair Altman December 28, 2013 at 09:47 Reply

      Yes, it is indeed possible. For previously-created uicontrols you’d need to use the findjobj function to get the underlying Java handle.

  23. Daniel April 24, 2014 at 23:48 Reply

    Hi Yair! Thanks a lot for your research on matlab!
    I’m more or less new to matlab (not to Java) and still have some problems with the usage of handles in matlab.
    I dynamicaly create edit-boxes and use some of the underlaying java-callbacks. But in the callback function itself I need to know the handle of the matlab edit-box in order to get its UserData. The handle passed to the calback function just seems to be a handle to a java class, not an object. When I try to pass the handle of the matlab uicontrol by adding a parameter it doesn’t work properly: in some cases it works, in other the handle points to an non existing object…
    Is there a way to get the matlab uicontrol handle inside the callback function?
    Here’s my code:

    function text_ButtonDownFcn(hObject, eventdata, handles)
    % This function creates the edit-boxes. Its itself a callback from a text-label. There are plenty of these text-labels but they all refer to this callback function. The text objectes contain some infos in there UserData. These i need.
        hTextEdit = uicontrol('Style','edit','String','someText','Units','normalized','Position',pos,'UserData',hObject);
     
        % set java callbacks
        jhTextEdit = findjobj(hTextEdit);
        set(jhTextEdit,'FocusLostCallback',{@textEdit_Callback, hTextEdit});
        set(jhTextEdit,'KeyReleasedCallback',{@textEdit_KeyReleasedCallback, hTextEdit});
     
        % set focus to text-edit
        uicontrol(hTextEdit); 
    end
     
    function textEdit_Callback(hObject, eventdata, hTextEdit)
        hText = get(hTextEdit,'UserData');
        neededInfos = get(hText,'UserData'); %  get; Invalid handle object; Why, the text object still exists!
    end

    function text_ButtonDownFcn(hObject, eventdata, handles) % This function creates the edit-boxes. Its itself a callback from a text-label. There are plenty of these text-labels but they all refer to this callback function. The text objectes contain some infos in there UserData. These i need. hTextEdit = uicontrol('Style','edit','String','someText','Units','normalized','Position',pos,'UserData',hObject); % set java callbacks jhTextEdit = findjobj(hTextEdit); set(jhTextEdit,'FocusLostCallback',{@textEdit_Callback, hTextEdit}); set(jhTextEdit,'KeyReleasedCallback',{@textEdit_KeyReleasedCallback, hTextEdit}); % set focus to text-edit uicontrol(hTextEdit); end function textEdit_Callback(hObject, eventdata, hTextEdit) hText = get(hTextEdit,'UserData'); neededInfos = get(hText,'UserData'); % get; Invalid handle object; Why, the text object still exists! end

    thanks a lot!

    • Yair Altman April 25, 2014 at 00:03 Reply

      @Daniel – you’re basically doing it correctly, but you can pass hObject as a separate parameter rather than go through UserData:

      set(jhTextEdit,'FocusLostCallback',{@textEdit_Callback, hTextEdit, hObject});
       
      function textEdit_Callback(hObject, eventdata, hTextEdit, hText)  % hText=hObject
          ...
      end

      set(jhTextEdit,'FocusLostCallback',{@textEdit_Callback, hTextEdit, hObject}); function textEdit_Callback(hObject, eventdata, hTextEdit, hText) % hText=hObject ... end

      The important point is that this handle (and its associated control) must exist when you try to access them.

    • Daniel April 25, 2014 at 00:04 Reply

      Okay, my fault. The text-label is destroyed and recreated. So nevermind!

      But it would be great to know it anyway: Is there a way to get the matlab uicontrol handle inside the callback function without passing it mayself?

      • Daniel April 25, 2014 at 00:06

        Wow, you’re fast!
        Thanks for your reply!

  24. Matlab callbacks for Java events in R2014a | Undocumented Matlab May 8, 2014 at 03:29 Reply

    […] five years ago, in one of this blog’s first articles, I wrote an article explaining how to trap the standard Java Swing events in Matlab, in order to achieve much more extensive behavior customizability than Matlab’s standard […]

  25. Sven September 30, 2014 at 00:44 Reply

    Hi Yair,

    first of all thank you for the great Job you are doing on MATLAB secrets for years now!

    I’ve got the following problem when using handles in R2013b:

    I am trying to develop a small tool for analyzing stored figures. A first step would be to react on a customer mouse click.

    I did this the following way:

    figure();
    plot(1:10);
    javaFrame = get(gcf, 'JavaFrame');
    hf = handle(javaFrame.fHG1Client.getAxisComponent, 'CallbackProperties')
    set(hf,'MouseClickedCallback',@ImageClickCallback);

    figure(); plot(1:10); javaFrame = get(gcf, 'JavaFrame'); hf = handle(javaFrame.fHG1Client.getAxisComponent, 'CallbackProperties') set(hf,'MouseClickedCallback',@ImageClickCallback);

    Everything works fine, the output of hf is

    hf =
    	javahandle_withcallbacks.com.mathworks.hg.peer.FigureAxisComponentProxy$_AxisCanvas

    hf = javahandle_withcallbacks.com.mathworks.hg.peer.FigureAxisComponentProxy$_AxisCanvas

    BUT if I try to work the same way with a stored figure, which I open by calling “openfig()” the following occurs:

    hf =
    	javahandle.com.mathworks.hg.peer.FigureAxisComponentProxy$_AxisCanvas
     
    Error using javahandle.com.mathworks.hg.peer.FigureAxisComponentProxy$_AxisCanvas/set
    The name 'MouseClickedCallback' is not an accessible property for an instance of class
    'com.mathworks.hg.peer.FigureAxisComponentProxy$_AxisCanvas'.

    hf = javahandle.com.mathworks.hg.peer.FigureAxisComponentProxy$_AxisCanvas Error using javahandle.com.mathworks.hg.peer.FigureAxisComponentProxy$_AxisCanvas/set The name 'MouseClickedCallback' is not an accessible property for an instance of class 'com.mathworks.hg.peer.FigureAxisComponentProxy$_AxisCanvas'.

    So my question is, how is it possible to make the handle returned by the openfig()-function a “javahandle_withcallbacks”????

    Thanks a lot!

    Regards
    Sven

    • Yair Altman September 30, 2014 at 05:03 Reply

      @Sven – I can’t think of an immediate solution. Once the _AxisCanvas object is created by openfig without the callbacks, you cannot add them later (see relevant comment within the javacomponent.m file.

      As an alternative, try using Matlab’s standard ButtonDownFcn callback. This might remove the need for using _AxisCanvas altogether.

  26. Can't get mouse callback to work with java swing - BlogoSfera June 29, 2015 at 15:43 Reply

    […] when the mouse is clicked or dragged along a slider. I have tried suggestions across blog posts (http://undocumentedmatlab.com/blog/uicontrol-callbacks) and the corresponding book. It seems to me that I am missing something. Here is the code:function […]

  27. Can’t get mouse callback to work with java swing | Solutions for enthusiast and professional programmers June 29, 2015 at 16:19 Reply

    […] when the mouse is clicked or dragged along a slider. I have tried suggestions across blog posts (http://undocumentedmatlab.com/blog/uicontrol-callbacks) and the corresponding book. It seems to me that I am missing something. Here is the […]

  28. How to capture key press in Matlab uipanel - DexPage July 25, 2015 at 23:28 Reply

    […] has focus? I’ve found that uipanel does not have the KeyPressFcn property. I’ve read this post from Undocumented Matlab about Java callbacks, but I also can’t get KeyPressedCallback to […]

  29. Error setting 'text' property of a Matlab uicontrol using its Java handle - BlogoSfera August 21, 2015 at 09:37 Reply

    […] am using Yair Altman’s findjobj function to add Java callbacks to my Matlab GUI. My goal is that each keypress inside the edittext (specifically arrow up, arrow […]

  30. Loops May 19, 2016 at 15:49 Reply

    Hi Yair
    Are there any callback controls in axes?
    I want monitor “PropertyCahnged” event.
    Or, re-create a class for axes?
    Thanks

    • Yair Altman May 19, 2016 at 23:39 Reply

      @Loops – axes are not uicontrols and they have an entirely different set of properties, events and callbacks. Search this blog for specific axes keywords and maybe you will find what you need.

  31. Efraim January 27, 2017 at 14:43 Reply

    Hi!
    Is there a callback function for the dropdown menu (popup) uicontrol, to execute only when one of the items is selected by the mouse or when the ‘enter’ button is pressed? The normal callback function executes with every keyboard press but I only want it to start executing when one of the items is selected (either by means of a ‘enter’ or a mouse click).

    Many thanks in advance!

    • Yair Altman January 27, 2017 at 14:50 Reply

      Use the ActionPerformedCallback

    • Efraim January 27, 2017 at 15:29 Reply

      Hi Yair,
      Thanks for your suggestion. I tried but it didn’t work the way I want it.
      Here’s an example.

      f=figure;
      u=uicontrol('style','popup','string',{'one','two','three','four'});
      jo=findjobj(u);
      jbh=handle(jo,'CallbackProperties');
      set(jbh,'ActionPerformedCallback','disp(123);')

      f=figure; u=uicontrol('style','popup','string',{'one','two','three','four'}); jo=findjobj(u); jbh=handle(jo,'CallbackProperties'); set(jbh,'ActionPerformedCallback','disp(123);')

      If I’d type ‘t’ it would select ‘two’ (and show 123 in the command line). But I don’t want it to show 123 just yet, only if I press enter, or if I had selected one of the items using the mouse.
      Hope it’s more clear!

      • Yair Altman January 28, 2017 at 19:23

        There is no specific Java callback that does exactly what you want as far as I know. You can possibly achieve this functionality by programmatic logic using a combination of the existing callbacks.

  32. Noah May 26, 2017 at 23:22 Reply

    Yair,

    Is there a generic way to pass a Matlab method to Java (that Java can execute) without having to use JFrame?
    e.g.

    classdef HelloWorld
       method
          function this = HelloWorld()
            %Pass HelloWorld.jar main entry point HellowWorld callback method
            a = HelloWorld;
            %Notional (here main is any HelloWorld class method, not limited to a JFrame callback)
            set(a,'main',{@this.callback,parm1,parm2,...})
          end
       end
       method
          function callback(parm1, parm2,...)
             ...
          end
       end
    end

    classdef HelloWorld method function this = HelloWorld() %Pass HelloWorld.jar main entry point HellowWorld callback method a = HelloWorld; %Notional (here main is any HelloWorld class method, not limited to a JFrame callback) set(a,'main',{@this.callback,parm1,parm2,...}) end end method function callback(parm1, parm2,...) ... end end end

    If this is do-able I’d be willing to donate numerous coffee’s 🙂

    Thanks in advance,
    Noah

    • Yair Altman May 28, 2017 at 12:23 Reply

      @Noah – yes, this is indeed possible but the Java class would need to be written in a specific way to enable Matlab callbacks for the Java events. Contact me offline (altmany at gmail) for assistance.

  33. Nipurn Jain March 13, 2018 at 08:57 Reply

    How to determine cursor position in ‘edit’ uicontrol?

    I have an application where there are several buttons that apply a specific function to the data. The user can also enter values in the edit box. However if the cursor is positioned in the edit box and a button is pressed the new function will appear at the end of the edit box and I need that this appear at cursor position how to do this?
    Is it possible by using javaframe available on matlab?

    • Nipurn Jain March 13, 2018 at 08:58 Reply

      I have an application where there are several buttons that apply a specific function to the data. The user can also enter values in the edit box. However if the cursor is positioned in the edit box and a button is pressed the new function will appear at the end of the edit box and I need that this appear at cursor position how to do this?

    • Yair Altman March 13, 2018 at 10:46 Reply

      see answer here

  34. maiky76 January 29, 2022 at 06:03 Reply

    Thanks for this great post.
    It’s got me up and running in no time.
    I have to make an Octave version of it and I am really struggling.

    Here is the code that behave as I’d like it to:
    Open external program, return to Matlab/Octave script, Matlab/Octave makes some keyboard inputs closes the program, then back to Matlab/Octave to finish the remaining commands of the script

    import java.awt.*;
    import java.awt.event.*;
     
    system('"calc.exe"&amp;');
     
    R2D2 = Robot;
    R2D2.delay(100) 
    R2D2.keyPress(KeyEvent.VK_8)
    R2D2.keyRelease(KeyEvent.VK_8)
    R2D2.delay(1000)  
    R2D2.keyPress(KeyEvent.VK_ALT)
    R2D2.keyPress(KeyEvent.VK_F4)
    R2D2.keyRelease(KeyEvent.VK_ALT)
    R2D2.keyRelease(KeyEvent.VK_F4)

    import java.awt.*; import java.awt.event.*; system('"calc.exe"&amp;'); R2D2 = Robot; R2D2.delay(100) R2D2.keyPress(KeyEvent.VK_8) R2D2.keyRelease(KeyEvent.VK_8) R2D2.delay(1000) R2D2.keyPress(KeyEvent.VK_ALT) R2D2.keyPress(KeyEvent.VK_F4) R2D2.keyRelease(KeyEvent.VK_ALT) R2D2.keyRelease(KeyEvent.VK_F4)

    with Octave I am stuck here

    % There is no import function 
    % OBJ = java_set/get (OBJ, NAME, VAL)
    % jobj = javaObject (classname, arg1, …)
    % Ret = javaMethod (methodname, obj, arg1, …)
     
    system("calc.exe", false, "async"); 
     
    R2D2 = javaObject("java.awt.Robot"); % OK
    methods (R2D2)
     
    R2D2.delay(5000); % OK
    % robot.keyPress (java.awt.event.KeyEvent.VK_SHIFT); KO

    % There is no import function % OBJ = java_set/get (OBJ, NAME, VAL) % jobj = javaObject (classname, arg1, …) % Ret = javaMethod (methodname, obj, arg1, …) system("calc.exe", false, "async"); R2D2 = javaObject("java.awt.Robot"); % OK methods (R2D2) R2D2.delay(5000); % OK % robot.keyPress (java.awt.event.KeyEvent.VK_SHIFT); KO

    R2D2 = javaObject(“java.awt.Robot”);
    methods (R2D2)

    R2D2 = javaObject(“java.awt.Robot”); methods (R2D2)

    shows that keyPress is a valid method so something along the lines of

    javaMethod (‘keyPress’, R2D2, , ...)

    javaMethod (‘keyPress’, R2D2, , ...)

    and

    R2D2.keyPress (, …`)

    R2D2.keyPress (, …`)

    should work.
    The problem is that as soon as the method call doesn’t painfully exactly conforms to the method “signature”, Octave is only able to signal that fact using the one error message it has there and that’s the NoSuchMethodException – even though the method DOES exist

    The reason why I am interested can we found here: Acoustic Horn Design – The Easy Way (Ath4) | Page 459 | diyAudio)
    We are trying to perform some optimization on the design of an DIY acoustic waveguide.
    Any help would be much appreciated!

    PS checkClass.m crashes Matlab 2018b

    • Yair Altman January 30, 2022 at 10:54 Reply

      Answer posted here: http://undocumentedmatlab.com/articles/gui-automation-robot#comment-513320

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