Exactly 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 uicontrols. Three years ago I wrote a related article showing how to trap any Java events as simple Matlab callbacks, even those from custom Java classes. This worked very well over the years, until now.
Over the past few weeks, several people have commented and emailed me about a problem that occurs in R2014a but not in earlier releases: Whereas Java objects in R2013b and earlier automatically exposed their public events as Matlab callbacks, they no longer do so in R2014a.
As a simple example to illustrate the point, let’s take a simple Java JButton and modify its label when the mouse moves over it, using the mouseEntered, mouseExited
events. In R2013b and earlier this was pretty easy:
% Create and display a simple JButton jButton = javax.swing.JButton('click me'); javacomponent(jButton, [50,50,80,20], gcf); % Set the Matlab callbacks to the JButton's events set(jButton, 'MouseEnteredCallback', @(h,e)set(jButton,'Text','NOW !!!')) set(jButton, 'MouseExitedCallback', @(h,e)jButton.setText('click me'))

(Note how I used two distinct variants to set the button’s text, using either the Matlabized Text property with the set function, or the standard JButton’s setText() method. We can use either of these variants: they are equivalent and largely a matter of personal taste, although the Java method is generally preferable.)
Unfortunately, in R2014a we get an error, since the jButton
object no longer exposes its events as Matlab callbacks:
>> set(jButton, 'MouseEnteredCallback', @(h,e)set(jButton,'Text','NOW !!!')) The name 'MouseEnteredCallback' is not an accessible property for an instance of class 'javax.swing.JButton'.
The solution – wrap the Java reference in a Matlab handle
Do not set Matlab callbacks on the so-called “naked” Java reference. Instead, wrap the reference with a Matlab handle:
>> jButton = handle(jButton, 'CallbackProperties'); hjButton = javahandle_withcallbacks.javax.swing.JButton % we can now set the callbacks on jButton as before
The simple act of using the handle wrapper rather than the naked Java reference also prevents some memory leaks, as I explained here. While you’re at it, also wrap (or more precisely, auto-delegate) the Java reference with a javaObjectEDT, if it is a Swing GUI component, in order to avoid EDT timing issues. Using these wrappers form two of my six rules for safe Java programming in Matlab, that I outlined in section 1.5 of my Matlab-Java programming book. Anyone who followed that advice would not need to modify their code for R2014a. Even if you didn’t, the solution is quite painless: simply add the wrapper line for any Java reference whose events you wish to trap.
Note that the explanation above relates to all Java objects that expose events, not just for GUI ones. I used JButton
merely to illustrate the point.
Related posts:
- Matlab callbacks for Java events Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...
- FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
- JMI – Java-to-Matlab Interface JMI enables calling Matlab functions from within Java. This article explains JMI's core functionality....
- Matlab-Java interface using a static control The switchyard function design pattern can be very useful when setting Matlab callbacks to Java GUI controls. This article explains why and how....