A CSSM reader recently asked whether it is possible to detect window focus events (specifically, the focus-gain event) asynchronously, so that such events can trigger a callback without necessitating a polling thread to constantly monitor the windows state.
The user correctly mentioned the fact that although mouse-clicks within the window frame can be detected using the documented figure callback WindowButtonDownFcn, there are other methods by which a window can gain focus: keyboard (<Alt>-<Tab> on Windows, for example), clicking the window frame edge etc. These methods are all undetected by WindowButtonDownFcn.
This problem is, to the best of my knowledge, insoluble using standard documented Matlab. However, there is indeed a simple solution using undocumented/unsupported Matlab features. The solution relies on the fact that all Matlab windows are basically Java Swing objects, and these objects have dozens of standard callback hooks that can be utilized (Matlab only exposes a few callbacks). The list of standard Swing callbacks was detailed in my earlier article about uicontrol callbacks, which is also relevant for Java window frames.
In this specific case, we are interested in FocusGainedCallback. This callback is invoked for the figure Frame’s AxisComponent (a part of the Frame that will be explained in another article). For each of our monitored figure windows, we set this callback to a predefined Matlab function. We may also wish to set its companion FocusLostCallback.
Here’s the resulting code snippet (hFig is our Matlab figure handle):
% Prepare the figure hFig = figure; % etc. - prepare the figure % Get the underlying Java reference warning off MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame jFig = get(hFig, 'JavaFrame'); jAxis = jFig.getAxisComponent; % Set the focus event callback set(jAxis,'FocusGainedCallback',{@myMatlabFunc,hFig}); % perhaps also set the FocusLostCallback here
Whenever any of the monitored figures now gets focus, by whichever means, the user-defined Matlab function myMatlabFunc() will be invoked. This function should be defined as follows:
function myMatlabFunc(jAxis, jEventData, hFig) % do whatever you wish with the event/hFig information end
Extra input parameters can be added during callback setup and definition, as follows:
set(jAxis,'FocusLostCallback',{@myMatlabFunc,hFig,data1,data2}) ... function myMatlabFunc(jAxis, jEventData, hFig, data1, data2) % do whatever you wish with the event/hFig/data information end
A very similar technique can detect other windowing events (maximization/minimization/movement etc.). Depending on the case, you may need to use jFig.fFigureClient.getWindow instead of jFig.getAxisComponent. The list of available callbacks for each of these objects can be seen using a simple set(jFig.getAxisComponent) command, or via my UIInspect or FindJObj utilities on the Matlab File Exchange.
Note that all this relies on the undocumented hidden figure property JavaFrame, which issues a standing warning (since Matlab release R2008a) of becoming obsolete in some future Matlab release. Since it worked so far, I have turned off this warning in the code above, but note that this code may well fail in some future Matlab version. If and when JavaFrame does become obsolete, be sure to look in this blog for workarounds…
Related posts:
- cprintf – display formatted color text in the Command Window cprintf is a utility that utilized undocumented Matlab desktop functionalities to display color and underline-styled formatted text in the Command Window...
- Setting status-bar text The Matlab desktop and figure windows have a usable statusbar which can only be set using undocumented methods. This post shows how to set the status-bar text....
- 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....
- EditorMacro v2 – setting Command Window key-bindings The EditorMacro utility was extended to support built-in Matlab Editor and Command-Window actions and key-bindings. This post describes the changes and the implementation details....
- Changing Matlab’s Command Window colors Matlab's Command Window foreground and background colors can be modified programmatically, using some of Matlab's undocumented internal Java classes. Here's how....
- Setting status-bar components Matlab status-bars are Java containers in which we can add GUI controls such as progress-bars, not just simple text labels...
Tags: FindJObj, GUI, Hidden property, Java, JavaFrame, UIInspect
Categories: Figure window, GUI, Hidden property, Java, Medium risk of breaking in future versions
This entry was posted
on Wednesday, September 9th, 2009 at 1:49 pm 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.

I think I found this in some of your code on the MathWorks file exchange, anyway if you don’t like having to turn warnings off you can use the undocumented use of handle as a function to get the underlying figure object and access the JavaFrame property from there without generating a warning.
Thanks for the great work Yair.
Hi,
I am working with a java component in matlab. I have wrapped a JTextArea and added a scroll and some features to it. I have two problems that I would like to solve:
1) I need a callback to use when something changes in the text area. I would like to use this to implement a UNDO, crl+z, feature. Do you know a suitable callback for this?
2) When I work with the text area it is very slow to render and repaint. If i delete some text, paste large blocks etc it might not render. I have tried calling repaint without success. Do you have a solution for this?
-David
@David – have a look here: http://UndocumentedMatlab.com/blog/uicontrol-callbacks/
I don’t have an immediate solution to the performance issue. JTextArea is usually performant, since it doesn’t have different fonts/styles like JEditorPane or JTextPane. Perhaps the bottleneck is in one of your callbacks or listeners?
Hey Yair,
It’s me again. I got a funny behavior when trying to access figure focus callbacks of saved figure. Here’s an example:
Open a plain figure with nothing in it and get the AxisComponent properties:
returns what we expect:
But, when this figure is saved and loaded again:
Now, AxisComponent properties are crippled:
The callback fields are no longer accessible among many others. Do you know why this happens and/or how to work around this problem to get to the focus callbacks?
TIA
Oops, I mistakenly placed “” text in MATLAB code block. For the first get(jAxis) returned values, there are many other Callback Fields between “MouseWheelMovedCallbackData = []” and ” KeyTypedCallback = “
@Kesh – this is an undocumented bug in the way Matlab loads FIG files – it loads Java objects without the ‘CallbackProperties’ argument (so some equivalent action), causing the object’s callbacks not to be visible in Matlab.
Apparently, only GUI figures and components created in run-time have accessible callbacks. This sounds odd, and I would love to learn how to bypass this limitation, but at the moment I don’t know if this is possible.
That’s a bummer. I wonder if there is any way for us to “attach” CallbackProperties after FIG is loaded… If you learn a way around for it, please let me know!
@Kesh – Even though the callback properties are not available the corresponding events are still generated. You can create listeners to them with:
It is not as convienent as the callback properties, but it works.
@Donn, thanks for the tip! That’ll do for me.