Archive for February, 2010

Inactive Control Tooltips & Event Chaining

Wednesday, February 24th, 2010

Once again, I welcome guest blogger Matt Whitaker, who continues his series of articles.

In my last post I explored some tips on tooltips. One of these tips involved displaying tooltips on disabled uicontrols. I explained that displaying tooltips on inactive controls is problematic since Matlab appears to intercept mouse events to these inactive controls, so even setting the tooltip on the underlying Java object will not work: The java object appears not to receive the mouse-hover event and therefore does not “know” that it’s time to display the tooltip.

When Yair and I deliberated this issue, he pointed me to his comment on a previous article showing an undocumented Java technique (Java also has some…) for forcing a tooltip to appear using the ActionMap of the uicontrol’s underlying Java object to get at a postTip action. We discussed using a WindowButtonMotionFcn callback to see if the mouse was above the inactive control, then triggering the forced tooltip display. Yair then went on to remind me and I quote: “you’ll need to chain existing WindowButtonMotionFcn callbacks and take into account ModeManagers that override them.”

Frankly, having written code previously that handles callback chaining, I would rather poke myself in the eye with a fork!

The Image Processing Toolbox has the nice pair of iptaddcallback and iptremovecallback functions that largely handle these issues. But for general Matlab, there seemed to be no alternative until I remembered that events trigger callbacks. I decided to use a listener for the WindowButtonMotion event to detect the mouse motion. Event listeners were briefly explained two weeks ago and deserve a dedicated future article. The advantage of using an event listener is that we don’t disturb any existing WindowButtonMotionFcn callback. We still need to be somewhat careful that our listeners don’t do conflicting things, but it’s a lot easier than trying to manage everything through the single WindowButtonMotionFcn.

A demonstration of this appears below with some comments following (note that this code uses the FindJObj utility):

function inactiveBtnToolTip
  %Illustrates how to make a tooltip appear on an inactive control
  h = figure('WindowButtonMotionFcn',@windowMotion,'Pos',[400,400,200,200]);
  col = get(h,'color');
  lbl = uicontrol('Style','text', 'Pos',[10,160,120,20], ...
                  'Background',col, 'HorizontalAlignment','left');
  btn = uicontrol('Parent',h, 'String','Button', ...
                  'Enable','inactive', 'Pos',[10,40,60,20]);
  uicontrol('Style','check', 'Parent',h, 'String','Enable button tooltip', ...
            'Callback',@chkTooltipEnable, 'Value',1, ...
            'Pos',[10,80,180,20], 'Background',col);
  drawnow;
 
  %create the tooltip and postTip action
  jBtn = findjobj(btn);
  import java.awt.event.ActionEvent;
  javaMethodEDT('setToolTipText',jBtn,'This button is inactive');
  actionMap = javaMethodEDT('getActionMap',jBtn);
  action = javaMethodEDT('get',actionMap,'postTip');
  actionEvent = ActionEvent(jBtn, ActionEvent.ACTION_PERFORMED, 'postTip');
 
  %get the extents plus 2 pixels of the control to compare to the mouse position
  btnPos = getpixelposition(btn)+[-2,-2,4,4]; %give a little band around the control
  left = btnPos(1);
  right = sum(btnPos([1,3]));
  btm = btnPos(2);
  top =  sum(btnPos([2,4]));
 
  % add a listener on mouse movement events
  tm = javax.swing.ToolTipManager.sharedInstance; %tooltip manager
  pointListener = handle.listener(h,'WindowButtonMotionEvent',@figMouseMove);
 
  %inControl is a flag to prevent multiple triggers of the postTip action
  %while mouse remains in the button
  inControl = false;
 
  function figMouseMove(src,evtData) %#ok
    %get the current point
    cPoint = evtData.CurrentPoint;
 
    if cPoint(1) >= left && cPoint(1) <= right &&...
       cPoint(2) >= btm  && cPoint(2) <= top
 
      if ~inControl %we just entered
        inControl = true;
        action.actionPerformed(actionEvent); %show the tooltip
      end %if
    else
      if inControl %we just existed
        inControl = false;
        %toggle to make it disappear when leaving button
        javaMethodEDT('setEnabled',tm,false);
        javaMethodEDT('setEnabled',tm,true);
      end %if
    end %if
  end %gpMouseMove
 
  function windowMotion(varargin)
    %illustrate that we can still do a regular window button motion callback
    set(lbl,'String',sprintf('Mouse position: %d, %d',get(h,'CurrentPoint')));
    drawnow;
  end %windowMotion
 
  function chkTooltipEnable(src,varargin)
    if get(src,'Value')
      set(pointListener,'Enable','on');
    else
      set(pointListener,'Enable','off');
    end %if
  end %chkTooltipEnable
end %inactiveBtnToolTip

Tooltip on an inactive button

Tooltip on an inactive button

Comments on the code:

  1. The code illustrates that we can successfully add an additional listener to listen for mouse motion events while still carrying out the original WindowButtonMotionFcn callback. This makes chaining callbacks much easier.
  2. The handle.listener object has an Enable property that we can use to temporarily turn the listener on and off. This can be seen in the chkTooltipEnable() callback for the check box in the code above. If we wanted to permanently remove the listener we would simply use delete(pointListener). Note that addlistener adds a hidden property to the object being listened to, so that the listener is tied to the object’s lifecycle. If you create a listener directly using handle.listener you are responsible for it’s disposition. Unfortunately, addlistener fails for HG handles on pre-R2009 Matlab releases, so we use handle.listener directly.
  3. The code illustrates a good practice when tracking rapidly firing events like mouse movement of handling reentry into the callback while it is still processing a previous callback. Here we use a flag called inControl to prevent the postTip action being continuously fired while the mouse remains in the control.
  4. I was unable to determine if there is any corresponding action for the postTip to dismiss tips so I resorted to using the ToolTipManager to toggle its own Enable property to cleanly hide the tooltip as the mouse leaves the control.

Each Matlab callback has an associated event with it. Some of the ones that might be immediately useful at the figure-level are WindowButtonDown, WindowButtonUp, WindowKeyPress, and WindowKeyRelease. They can all be accessed through handle.listener or addlistener as in the code above.

Unfortunately, events do not always have names that directly correspond to the callback names. In order to see the list of available events for a particular Matlab object, use the following code, which relies on another undocumented function – classhandle. Here we list the events for gcf:

>> get(get(classhandle(handle(gcf)),'Events'),'Name')
ans = 
    'SerializeEvent'
    'FigureUpdateEvent'
    'ResizeEvent'
    'WindowKeyReleaseEvent'
    'WindowKeyPressEvent'
    'WindowButtonUpEvent'
    'WindowButtonDownEvent'
    'WindowButtonMotionEvent'
    'WindowPostChangeEvent'
    'WindowPreChangeEvent'

Note that I have made extensive use of the javaMethodEDT function to execute Java methods that affect swing components on Swing’s Event Dispatch Thread. I plan to write about this and related functions in my next article.

Additional uicontrol tooltip hacks

Wednesday, February 17th, 2010

Once again I’d like to welcome guest blogger Matthew Whitaker. Today Matt will discuss uicontrol tooltips hacks as the first of several posts that follow a logical thread culminating in the long promised article on the EDT.

A while back Yair wrote a cool article, Spicing up Matlab uicontrol tooltips, describing use of HTML formatting and images in uicontrol tooltips. I want to share some limitations I’ve seen with tooltips and their solution using the Matlab control’s underlying Java object.

Situation 1: Displaying a tooltip on disabled controls

One issue with the stock Matlab uicontrol tooltips is that if you turn the uicontrol’s Enable property to ‘inactive’ or ‘off’, its tooltip no longer displays. This is the behavior that we normally want, but occasionally we wish to display a tooltip on a disabled control, for example, to explain why the control is disabled.

You can use the findjobj utility to find the Java handle for the uicontrol. This handle can then be used to set the tooltip text. The tooltip will display if you disable the control using its Java handle’s Enabled property rather than the Matlab handle’s Enable property:

hButton = uicontrol('String','Button');
drawnow;
jButton= findjobj(hButton);
set(jButton,'Enabled',false);
set(jButton,'ToolTipText','This is disabled for a reason');

As customary for Java objects, its properties can also be set using their corresponding accessor methods:

javaMethodEDT('setEnabled',jButton,false);
javaMethodEDT('setToolTipText',jButton,'Button is disabled for a reason');

tooltip on a disabled uicontrol

tooltip on a disabled uicontrol

Unfortunately, this hack does not work for ‘inactive’ controls. There is no direct Java analogy for inactive controls – it’s a Matlab extension. It appears that Matlab somehow intercepts the mouse events associated with inactive controls. My next post will show how event callback can be used to display tooltips for inactive controls.

As an alternative for inactive edit-box controls, we can simulate the inactive behavior by setting the Java object’s Editable property (or by using its setEditable() accessor method), then setting the tooltip. Note that the extremely-useful Java Editable property is unavailable in the Matlab handle, for some inexplicable reason:

hEditbox = uicontrol('String','Edit Text','Style','edit');
drawnow;
jEditbox = findjobj(hEditbox);
set(jEditbox,'Editable',false);
set(jEditbox,'ToolTipText','Text is inactive for a reason');

tooltip on a non-editable editbox

tooltip on a non-editable editbox

Situation 2: Displaying a tooltip on truncated text

If we want to conditionally display a tooltip for an editbox uicontrol when the text exceeds the control’s width, we can use the TipWhenTruncatedEnabled property (or its corresponding setTipWhenTruncatedEnabled() method). This will display a tooltip with the editbox contents if the string is shown truncated. This saves the user having to scroll through the control to see its contents. I often use this for edit controls that may contain long path names:

hEditbox(1) = uicontrol('Style','edit','Units','norm','Pos',[0.1,0.8,0.4,0.05], 'String','Too Short');
hEditbox(2) = uicontrol('Style','edit','Units','norm','Pos',[0.1,0.7,0.2,0.05], 'String','Long Enough to Display a Tool Tip');
drawnow;
jEditbox1 = findjobj(hEditbox(1));
jEditbox2 = findjobj(hEditbox(2));
set(jEditbox1,'TipWhenTruncatedEnabled',true);  % property-based alternative
javaMethod('setTipWhenTruncatedEnabled',jEditbox2,true);  % method-based alternative

TipWhenTruncatedEnabled tooltip

TipWhenTruncatedEnabled tooltip

The TipWhenTruncatedEnabled property property is also available for multi-line editboxes, but has (obviously) no effect when scrollbars are present. Also note that setting the TipWhenTruncatedEnabled property to true overrides any previous tooltip that might have been set for the editbox.

Finally, note that the TipWhenTruncatedEnabled property can also be set for the editbox component of popup-menu (aka drop-down) controls, after they have been set to be editable using their Java Editable property (note that both properties are false by default for Matlab uicontrols). In the following screenshot, the drop-down’s editbox component contained an HTML snippet, that is shown unformatted within the edit-box and HTML-formatted in the de-truncated tooltip:

de-truncated HTML-format tooltip

de-truncated HTML-format tooltip

Situation 3: Controlling tooltip timing

As you have probably noticed, there is a slight delay between the time your mouse enters the control and when the tooltip actually appears. If you display a tooltip over a control for sufficiently long the tooltip will then disappear. Sometimes the default delays are too slow or fast for your application. These times can be controlled through the javax.swing.ToolTipManager. The ToolTipManager sets these parameters globally (including for your Matlab desktop components), but they are not persistent between sessions.

Some examples using the ToolTipManager:

btn = uicontrol('String','Button','Tooltip','This is a button.','Pos',[100,100,75,25]);
txt = uicontrol('Style','edit','String','Edit Text','Tooltip','This is editable text','Pos',[100,50,75,25]);
 
tm = javax.swing.ToolTipManager.sharedInstance; %static method to get ToolTipManager object
initialDelay = javaMethodEDT('getInitialDelay',tm); %get the delay before display in milliseconds (=750 on my system)
javaMethodEDT('setInitialDelay',tm,0); %set tooltips to appear immediately
 
dismissDelay = javaMethodEDT('getDismissDelay',tm); %get the delay before the tooltip disappears (=10000 (10 sec) on my system)
javaMethodEDT('setDismissDelay',tm,2000); %set the dismiss delay to 2 seconds
 
javaMethodEDT('setEnabled',tm,false); %turns off all tooltips in system (including the Matlab desktop)
javaMethodEDT('setEnabled',tm,true);
 
javaMethodEDT('setInitialDelay',tm,initialDelay);
javaMethodEDT('setDismissDelay',tm,dismissDelay);

Note that I have made extensive use of the undocumented built-in javaMethodEDT function to execute Java methods that affect Swing components on the Swing Event Dispatch Thread (EDT). I plan to write about EDT following my next post on event callback chaining.

Continuous slider callback

Monday, February 8th, 2010

Every few months, a CSSM forum reader asks how to set up a continuously-invoked slider callback: Matlab’s slider uicontrol invokes the user callback only when the mouse button is released, and not continuously while the slider’s thumb is dragged. This functionality was again referred-to yesterday, and I decided it merits a dedicated post.

There are three distinct simple ways to achieve continuous callbacks:

Using Java callbacks

As explained in an earlier article, Matlab uicontrols are basically Java Swing objects that possess a large number of useful callbacks. Matlab sliders’ underlying Java objects, which are really not JSliders but JScrollBars, have an AdjustmentValueChangedCallback property that is useful for our purposes and is accessible using the FindJObj utility. Simply download FindJObj from the File Exchange, and then:

hSlider = uicontrol('style','slider', ...);
jScrollBar = findjobj(hSlider);
jScrollBar.AdjustmentValueChangedCallback = @myCbFcn;
% or: set(jScrollBar,'AdjustmentValueChangedCallback',@myCbFcn)

Where myCbFcn is the Matlab callback function that will be invoked continuously when the arrow buttons are depressed or the slider’s thumb is dragged.

Using an event listener

An alternative to the Java route is to use Matlab’s undocumented handle.listener function to listen to the slider’s Action event, as follows:

hListener = handle.listener(hSlider,'ActionEvent',@myCbFcn);

This alternative is used by Matlab’s own imscrollpanel function:

if isJavaFigure
   % Must use these ActionEvents to get continuous events fired as slider
   % thumb is dragged. Regular callbacks on sliders give only one event
   % when the thumb is released.
   hSliderHorListener = handle.listener(hSliderHor,...
      'ActionEvent',@scrollHorizontal);
   hSliderVerListener = handle.listener(hSliderVer,...
      'ActionEvent',@scrollVertical);
   setappdata(hScrollpanel,'sliderListeners',...
      [hSliderHorListener hSliderVerListener]);
else
   % Unfortunately, the event route is only available with Java Figures,
   % so platforms without Java Figure support get discrete events only
   % when the mouse is released from dragging the slider thumb.
   set(hSliderHor,'callback',@scrollHorizontal)
   set(hSliderVer,'callback',@scrollVertical)
end

Using a property listener

The handle.listener function can also be used to listen to property value changes. In our case, set a post-set listener, that gets triggered immediately following Value property updates, as follows:

hhSlider = handle(hSlider);
hProp = findprop(hhSlider,'Value');  % a schema.prop object
hListener = handle.listener(hhSlider,hProp,'PropertyPostSet',@myCbFcn);

In addition to ‘PropertyPostSet’, we could also listen on ‘PropertyPreSet’, which is triggered immediately before the property is modified. There are also corresponding ‘*Get’ options. In relatively old Matlab releases (I believe R2007b and earlier, but I’m not certain), the option names were simply ‘PostSet’, ‘PreSet’ etc., without the ‘Property’ prefix.

Do you know of any other way to achieve continuous callbacks? If so, I would be delighted to hear in the comments section below.

Solving a MATLAB bug by subclassing

Sunday, February 7th, 2010

I would like to welcome guest blogger Matthew Whitaker. Many of Matt’s CSSM submissions offer important insight of internal Matlab functionality. As shall be seen by today’s article and some future submissions, Matt has plenty to share vis-a-vis Matlab’s undocumented functionality.

In my day-to-day work I make extensive use of MATLAB’s Image Processing Toolbox (IPT). One area of the toolbox that has seen considerable change over the last few releases has been the development of a set of modular tools to aid in GUI design for image processing applications. In this article, I examine a bug in one of those tools to illustrate how we can use the power of subclassing these objects (using an undocumented property) to design a simple and effective workaround.

The problem

The problem arose as I was refactoring some code that was written in R2006b to R2009b. The code in question uses the impoint tool on an image along with an associated text object that moves with the point to display information as it is dragged around the image. At the time of the R2006b release the impoint tool was written as an API. In R2006b the call to impoint returns a handle to an hggroup containing a structure of function handles in its application data under the tag ‘API’. This programming pattern was common before the advent of the new class syntax in MATLAB version 7.6 (R2008a).

Here is an example of how impoint would be used in R2006b:

function impointBehavior_R2006b
%IMPOINTBEHAVIOR_R2006B shows how impoint would be used in R2006b
%Note: RUN UNDER R2006B (will run under R2009b but actually uses
%classdef impoint so it will show the same issue)
 
  % Display the image in a figure window
  figure;  imshow('rice.png');
 
  % In R2006b calling impoint returns the hggroup handle
  h = impoint(gca,100,200);
 
  % In 2006b iptgetapi returns a structure of function handles
  api = iptgetapi(h);
 
  % Add a new position callback to set the text string
  api.addNewPositionCallback(@newPos_Callback);
 
  % Construct boundary constraint function so we can't go outside the axes
  fcn = makeConstrainToRectFcn('impoint',get(gca,'XLim'),get(gca,'YLim'));
  api.setDragConstraintFcn(fcn);
 
  % Fire callback so we get initial text
  newPos_Callback(api.getPosition());
 
  function newPos_Callback(newPos)
    % Display the current point position in a text label
    api.setString(sprintf('(%1.0f,%1.0f)',newPos(1),newPos(2)));
  end %newPos_Callback
 
end %impointBehavior_R2006b

The code above, when run in R2006b, produces the desired behavior of displaying a text object containing the point coordinates that moves around with the point as it is dragged around the axes.

In R2009b, impoint is now a true MATLAB class using the new classdef syntax, so I wanted to update the existing code. Initially this appeared to be a straightforward translation of the code to make use of the new impoint class syntax. The first attempt to rewrite the code was:

function impointBehavior_R2009b
%IMPOINTBEHAVIOR_R2009B shows the undesirable behavior when
%using the setString method in R2009b. 
 
  % Display the image in a figure window
  figure;  imshow('rice.png');
  h = impoint(gca,100,200);
 
  % Add a new position callback to set the text string
  h.addNewPositionCallback(@newPos_Callback);
 
  % Construct boundary constraint function so we can't go outside the axes
  fcn = makeConstrainToRectFcn('impoint',get(gca,'XLim'),get(gca,'YLim'));
 
  % Enforce boundary constraint function
  h.setPositionConstraintFcn(fcn);
 
  % Fire callback so we get initial text
  newPos_Callback(h.getPosition());
 
  function newPos_Callback(newPos)
    % Display the current point position in a text label
    h.setString(sprintf('(%1.0f,%1.0f)',newPos(1),newPos(2)))
  end %newPos_Callback
 
end %impointBehavior_R2009b

Unfortunately, when this code is run, dragging the mouse around the axes produces a trail of labels as shown below:

Before - buggy behavior

Before - buggy behavior

Opening up impoint.m in the editor and tracing the code revealed that impoint’s setString method creates a new text object each time it is used. I reported this to MATLAB and the bug is now documented on the MathWorks Support site (574846).

The solution

So how do we work around this bug to get to the behavior we want? One solution would be to rewrite the offending MATLAB code but this is somewhat risky in terms of maintainability and compatibility.

A more elegant solution is to subclass the impoint class and substitute the setString behavior we want. Looking at the impoint code we find that impoint is a subclass of imroi. In the imroi property declarations we see a number of undocumented properties that are protected. We can access these properties in a subclass but not outside the class. One of these undocumented properties is h_group which is an hggroup that contains the handle graphic objects that make up the impoint on the screen. The label, when created, becomes part of this hggroup with its Tag property set to ‘label’. When performing the setString method the behavior we want to see is that if the text object exists we want to update its String property. If it does not exist we want it to perform its existing functionality:

classdef impointtextupdate < impoint
%IMPOINTTEXTUPDATE subclasses impoint to override the setString
%method of impoint so that it does not create a new text object
%each time it is called.   
 
  methods
    function obj = impointtextupdate(varargin)
      obj = obj@impoint(varargin{:});
    end %impointtextupdate
 
    function setString(obj,str)
      %override impoint setString
 
      %check to see if there is already a text label
      label = findobj(obj.h_group,'Type','text','Tag','label');
 
      if isempty(label)
        %do the default behavior
        setString@impoint(obj,str);
      else
        %update the existing tag
        set(label(1),'String',str);
      end %if
    end %setString
 
  end %methods
end %impointtextupdate

Substituting calls to impoint with the new impointupdatetext subclass now produces the desired effect as shown below:

After - expected behavior

After - expected behavior

Conclusions

This case illustrates a couple of points:

  • Much of the existing code in the MATLAB toolboxes is being updated to the new object oriented syntax. This presents many opportunities to easily and elegantly modify the default behavior without modifying provided toolbox code In the example above we retain all the desirable behavior of impoint while overriding the undesirable behavior.
  • Many of the properties and methods in the provided toolbox objects are hidden or protected and are undocumented. It takes some simple detective work to find these out through examining the code. MATLAB is very generous in providing much of the existing code openly. Open the functions and classes you use in the editor to really find out how they work. Over the years I’ve learned and adopted a lot of useful MATLAB programming patterns by examining the code in the various toolboxes (there are a few coding horrors as well!).

I hope to explore some other under-documented features of the IPT and other toolboxes in future posts.

Customizing listbox & editbox scrollbars

Monday, February 1st, 2010

A few days ago, a CSSM forum reader asked how to modify Matlab’s listbox scrollbars. Another user asked how to configure line-wrapping. I thought this is a good opportunity to describe how listbox and editbox scrollbars can be customized. The timing is particularly opportune, after I have recently described how the Matlab Editbox can be customized by accessing its underlying Java object using the FindJObj utility.

Both the listbox and the multi-line editbox uicontrols share a similar design: a multi-line Java control embedded within a JViewport within a JScrollPane (note that for historical reasons, the Java view-port class is called JViewport rather than the more standard camel-cased JViewPort). In addition to the view-port, the containing scroll-pane also contains two scrollbars (horizontal and vertical), as expected from standard Java scroll-panes.

JScrollPane components

JScrollPane components

Scrollbar policies

Control of the scroll-pane’s scrollbar behavior is done via the JScrollPane’s VerticalScrollBarPolicy and HorizontalScrollBarPolicy properties.

VerticalScrollBarPolicy accepts the self-explanatory values of:

  • VERTICAL_SCROLLBAR_ALWAYS (=22)
  • VERTICAL_SCROLLBAR_NEVER (=21)
  • and VERTICAL_SCROLLBAR_AS_NEEDED (=20)

HorizontalScrollBarPolicy accepts:

  • HORIZONTAL_SCROLLBAR_ALWAYS (=32)
  • HORIZONTAL_SCROLLBAR_NEVER (=31)
  • and HORIZONTAL_SCROLLBAR_AS_NEEDED (=30)

All these properties are static enumerated constants that can be referred using either their Java notation (e.g., JScrollPane.VERTICAL_SCROLLBAR_ALWAYS) or their equivalent numeric values. Using the non-numeric format is better, since it is more readable and the numeric values may change, but the choice is yours.

By default, Matlab implements a VerticalScrollBarPolicy of VERTICAL_SCROLLBAR_ALWAYS for sufficiently tall uicontrols (>20-25 pixels, which practically means always) and VERTICAL_SCROLLBAR_NEVER for shorter uicontrols.

For the horizontal scrollbar, Matlab implements a HorizontalScrollBarPolicy of HORIZONTAL_SCROLLBAR_NEVER for all editboxes and for narrow listboxes (<35 pixels), and HORIZONTAL_SCROLLBAR_AS_NEEDED for wide listboxes.

These settings are generally satisfactory. However, in some cases users may wish to modify the settings. For example, the default VerticalScrollBarPolicy setting of VERTICAL_SCROLLBAR_ALWAYS causes the vertical scrollbar to appear even when unneeded (the entire editbox content is visible). Also, we may wish to have a horizontal scrollbar on narrow listboxes and editboxes, something that the standard HORIZONTAL_SCROLLBAR_NEVER prevents. In both cases, a *_SCROLLBAR_AS_NEEDED policy might be more appropriate.

To modify these settings, we simply need to get the uicontrol’s underlying Java reference handle (using the FindJObj utility), and modify the appropriate property. For example:

% Create a multi-line (Max>1) editbox uicontrol
hEditbox = uicontrol('style','edit', 'max',5, ...);
 
% Get the Java scroll-pane container reference
jScrollPane = findjobj(hEditbox);
 
% Modify the scroll-pane's scrollbar policies
% (note the equivalent alternative methods used below)
set(jScrollPane,'VerticalScrollBarPolicy',20);  % or: jScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
jScrollPane.setHorizontalScrollBarPolicy(30);  % or: jScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED

default scrollbars (VERTICAL_SCROLLBAR_ALWAYS)

default scrollbars (VERTICAL_SCROLLBAR_ALWAYS)

non-default scrollbars (VERTICAL_SCROLLBAR_AS_NEEDED)     non-default scrollbars (VERTICAL_SCROLLBAR_AS_NEEDED)

non-default scrollbars (VERTICAL_SCROLLBAR_AS_NEEDED)

Note that updating the uicontrol handle (hEditbox)’s Position property has the side-effect of automatically reverting the scrollbar policies to their default values (HORIZONTAL_SCROLLBAR_NEVER and VERTICAL_SCROLLBAR_ALWAYS/NEVER). This also happens whenever the uicontrol is resized interactively (by resizing its container figure window, for example). It is therefore advisable to set jScrollPane’s ComponentResizedCallback property to “unrevert” the policies:

cbStr = sprintf('set(gcbo,''VerticalScrollBarPolicy'',%d)', ...
                jScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
hjScrollPane = handle(jScrollPane,'CallbackProperties');
set(hjScrollPane,'ComponentResizedCallback',cbStr);

Line-wrapping

By default, line-wrapping is turned on, effectively disabling horizontal scrolling (which is why Matlab set the HorizontalScrollBarPolicy to HORIZONTAL_SCROLLBAR_NEVER. However, in some cases it may be more useful to turn line-wrapping off and horizontal scrolling on using the TextArea’s setWrapping() method. Here’s a usage example:

jViewPort = jScrollPane.getViewport;
jEditbox = jViewPort.getComponent(0);
jEditbox.setWrapping(false);  % do *NOT* use set(...)!!!
newPolicy = jScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED;
set(jScrollPane,'HorizontalScrollBarPolicy',newPolicy);

multi-line editbox with wrapping on

multi-line editbox with wrapping on

multi-line editbox with wrapping off

multi-line editbox with wrapping off

Notes:

  1. setWrapping() only works for the default EditorKit, and fails for HTMLEditorKit – This is due to HTML’s inherent wrapping behavior, as can easily be seen in any browser webpage.
  2. while setWrapping() may seem like a regular setter method for a Wrapping property, in reality it is not. Actually, set(jEditbox,’wrapping’,flag) may crash Matlab. So, always use the setWrapping(flag) method variant, which is entirely safe.