An aspect of Matlab GUIs that include Java components that is often encountered (most recently reported yesterday) and is easily fixed, is Matlab’s default exclusion of all javacomponents from its focus traversal cycle.
This means that if we place several uicontrols and javacomponents together onscreen, clicking TAB or Shift-TAB will only move the focus between the regular uicontrols, but none of the javacomponents. The javacomponents can still get the focus, but only programmatically or by mouse click – not by keyboard-clicking TAB or Shift-TAB.
h1 = uicontrol('style','edit','position', [10 10 150 20]); h2 = uicontrol('style','edit','position', [10 40 150 20]); h3 = javacomponent(javax.swing.JTextField, [10 70 150 20]);
Java Swing components have several focus-related properties (and accessor methods) that relate to the component’s focus cycle, i.e. selecting (=setting the focus on) the component using the keyboard (overview; technical description).
Matlab documentation calls the focus cycle “tab-order” but only allows selecting the focus cycle order, using the uistack function – for all the extra functionality we need to use these Java properties.
The astute reader of this blog will of course have noticed that the Java component’s Focusable property is set to true and would therefore be justifiably puzzled as to why the cycle-focus doesn’t work.
Luckily, and counter-intuitively, the fix to the focus-cycle problem in Matlab GUI is extremely simple and requires no deep understanding of Java’s focus policy. Simply override the Java component’s Focusable property to true (explanation below):
h3.setFocusable(true); h3.putClientProperty('TabCycleParticipant', true); % this may be unnecessary in some cases, but doesn't hurt
This sounds crazy – After all, if the Focusable property is already true, what’s the use of updating its value to the same value???
The answer is that by setting Focusable to true, we indirectly invoke a back-end Java method that resets the component’s focus policy to its standard behavior, effectively overriding Matlab’s default (non-standard) focus policy.
Such a tricky problem… Such a long detective hunt for an answer… Such a simple and effective fix… – Just the way I like it 🙂