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:
- Additional uicontrol tooltip hacks Matlab's uicontrol tooltips have several limitations that can be overcome using the control's underlying Java object....
- 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....
- Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
- Setting listbox mouse actions Matlab listbox uicontrol can be modified to detect mouse events for right-click context menus, dynamic tooltips etc....
- uicontrol side-effect: removing figure toolbar Matlab's built-in uicontrol function has a side-effect of removing the figure toolbar. This was undocumented until lately. This article describes the side-effect behavior and how to fix it....
- Adding a context-menu to a uitree uitree is an undocumented Matlab function, which does not easily enable setting a context-menu. Here's how to do it....
Tags: callbacks, FindJObj, GUI, Java, uicontrol, UIInspect
Categories: GUI, Java, Low risk of breaking in future versions, UI controls
This entry was posted
on Friday, May 1st, 2009 at 2:58 am PST
You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.

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)?
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
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.
@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
[...] 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. [...]
[...] Matlab listbox uicontrol can be modified to detect mouse events for right-click context menus, dynamic tooltips etc. [...]
[...] The list of standard Swing callbacks was detailed in my earlier article about uicontrol callbacks, which is also relevant for Java windows [...]
[...] explained in an earlier article, Matlab uicontrols are basically Java Swing objects that possess a large number of useful callbacks [...]
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.
[...] 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. [...]