- Undocumented Matlab - https://undocumentedmatlab.com -

Uicontrol callbacks

In my previous post I showed how we can extensively customize a Matlab uicontrol’s appearance and behavior [1] 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:

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 [2] 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 [3].
Another typical usage is to set a continuously-firing callback whenever a slider uicontrol is dragged [4] – 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 [5] 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 [6] and may even be disabled in some future Matlab release [7]:

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.

69 Comments (Open | Close)

69 Comments To "Uicontrol callbacks"

#1 Comment By sleesh On May 5, 2009 @ 13:00

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)?

#2 Comment By Yair Altman On May 6, 2009 @ 12:27

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

#3 Comment By junziyang On May 15, 2009 @ 18:57

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.

#4 Comment By Yair Altman On May 16, 2009 @ 10:34

@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

#5 Pingback By EditorMacro – assign a keyboard macro in the Matlab editor | Undocumented Matlab On July 1, 2009 @ 12:18

[…] 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. […]

#6 Pingback By Setting listbox mouse actions | Undocumented Matlab On August 13, 2009 @ 15:31

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

#7 Pingback By Detecting window focus events | Undocumented Matlab On September 9, 2009 @ 13:50

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

#8 Pingback By Continuous slider callback | Undocumented Matlab On February 8, 2010 @ 02:13

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

#9 Comment By Yair Altman On March 9, 2010 @ 02:32

In answer to a [14] 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 [7].

Also see the following related CSSM threads [15] and [16].

#10 Pingback By JIDE Property Grids | Undocumented Matlab On April 21, 2010 @ 23:02

[…] 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. […]

#11 Comment By iroln On November 4, 2010 @ 09:05

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

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.

#12 Comment By Donn Shull On November 4, 2010 @ 10:18

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

Donn

#13 Comment By iroln On November 4, 2010 @ 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.

#14 Comment By Donn Shull On November 4, 2010 @ 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.

#15 Comment By iroln On November 4, 2010 @ 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)

But it didn’t help 🙂

The following Callback works only within that PanelContainer:

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

#16 Comment By Donn Shull On November 5, 2010 @ 08:53

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

#17 Comment By Yair Altman On November 7, 2010 @ 15:40

@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

#18 Comment By iroln On November 10, 2010 @ 14:11

Thanks, Yair Altman!

#19 Comment By Sean Larkin On December 7, 2010 @ 12:12

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?

#20 Comment By Yair Altman On December 7, 2010 @ 12:59

@Sean – take a look at: [17]

Related articles:
[18]
[19]

– Yair

#21 Comment By Janos Marki On January 30, 2011 @ 05:12

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');

…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

Thanks!
Janos

#22 Comment By Janos Marki On January 30, 2011 @ 07:27

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');
 

#23 Comment By Dave On January 3, 2012 @ 08:35

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

output:

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

#24 Comment By Yair Altman On January 5, 2012 @ 03:05

@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.

#25 Pingback By Matlab-Java memory leaks, performance | Undocumented Matlab On January 20, 2012 @ 04:52

[…] 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 […]

#26 Comment By Keith On March 2, 2012 @ 18:24

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

#27 Comment By Oscar On September 7, 2012 @ 08:53

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!

#28 Comment By Yair Altman On September 8, 2012 @ 10:49

@Oscar – take a look at the figure’s [20] property

#29 Pingback By uiinspect | Undocumented Matlab On January 23, 2013 @ 11:01

[…] 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. […]

#30 Comment By Vladimir On February 28, 2013 @ 08:42

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

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);

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

#31 Comment By Malcolm Lidierth On February 28, 2013 @ 08:53

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

#32 Comment By Vladimir On March 1, 2013 @ 00:56

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 ('');

in the the method which is hiding the tooltip.

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

#33 Comment By Malcolm Lidierth On March 2, 2013 @ 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, [21].
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 [22].

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.

#34 Comment By Sebastian K. On April 14, 2013 @ 12:42

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

#35 Comment By Yair Altman On April 14, 2013 @ 14:01

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

#36 Comment By Malcolm Lidierth On April 14, 2013 @ 15:35

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)')

#37 Comment By Sebastian K. On April 14, 2013 @ 15:52

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

#38 Comment By Sebastian K. On April 14, 2013 @ 16:00

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

#39 Pingback By Editbox data input validation | Undocumented Matlab On October 2, 2013 @ 10:09

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

#40 Comment By Lauren On October 7, 2013 @ 10:49

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)

Thanks for any help you can provide!

#41 Comment By Yair Altman On October 7, 2013 @ 10:55

@Lauren – my very recent article, that I have posted only a few days ago, discusses this issue exactly:
[23]

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.

#42 Comment By xay lee On November 24, 2013 @ 01:33

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

#43 Comment By Yair Altman On November 24, 2013 @ 07:36

@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.

#44 Comment By Charlie On December 28, 2013 @ 09:35

Hi Yair:

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

Best regards,

Charlie

#45 Comment By Yair Altman On December 28, 2013 @ 09:47

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

#46 Comment By Daniel On April 24, 2014 @ 23:48

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

thanks a lot!

#47 Comment By Yair Altman On April 25, 2014 @ 00:03

@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

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

#48 Comment By Daniel On April 25, 2014 @ 00:04

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?

#49 Comment By Daniel On April 25, 2014 @ 00:06

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

#50 Pingback By Matlab callbacks for Java events in R2014a | Undocumented Matlab On May 8, 2014 @ 03:29

[…] 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 […]

#51 Comment By Sven On September 30, 2014 @ 00:44

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);

Everything works fine, the output of hf is

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'.

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

#52 Comment By Yair Altman On September 30, 2014 @ 05:03

@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.

#53 Pingback By Can't get mouse callback to work with java swing – BlogoSfera On June 29, 2015 @ 15:43

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

#54 Pingback By Can’t get mouse callback to work with java swing | Solutions for enthusiast and professional programmers On June 29, 2015 @ 16:19

[…] when the mouse is clicked or dragged along a slider. I have tried suggestions across blog posts ( [25]) and the corresponding book. It seems to me that I am missing something. Here is the […]

#55 Pingback By How to capture key press in Matlab uipanel – DexPage On July 25, 2015 @ 23:28

[…] 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 […]

#56 Pingback By Error setting 'text' property of a Matlab uicontrol using its Java handle – BlogoSfera On August 21, 2015 @ 09:37

[…] 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 […]

#57 Comment By Loops On May 19, 2016 @ 15:49

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

#58 Comment By Yair Altman On May 19, 2016 @ 23:39

@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.

#59 Comment By Efraim On January 27, 2017 @ 14:43

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!

#60 Comment By Yair Altman On January 27, 2017 @ 14:50

Use the ActionPerformedCallback

#61 Comment By Efraim On January 27, 2017 @ 15:29

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);')

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!

#62 Comment By Yair Altman On January 28, 2017 @ 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.

#63 Comment By Noah On May 26, 2017 @ 23:22

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

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

Thanks in advance,
Noah

#64 Comment By Yair Altman On May 28, 2017 @ 12:23

@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.

#65 Comment By Nipurn Jain On March 13, 2018 @ 08:57

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?

#66 Comment By Nipurn Jain On March 13, 2018 @ 08:58

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?

#67 Comment By Yair Altman On March 13, 2018 @ 10:46

see answer [26]

#68 Comment By maiky76 On January 29, 2022 @ 06:03

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"&');

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
R2D2 = javaObject(“java.awt.Robot”);
methods (R2D2)

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

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

and

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: [27]
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

#69 Comment By Yair Altman On January 30, 2022 @ 10:54

Answer posted here: [28]