Continuous slider callback

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.

Bookmark and Share

Related posts:

  1. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  2. Setting listbox mouse actions Matlab listbox uicontrol can be modified to detect mouse events for right-click context menus, dynamic tooltips etc....
  3. Uicontrol callbacks This post details undocumented callbacks exposed by the underlying Java object of Matlab uicontrols, that can be used to modify the control's behavior in a multitude of different events...
  4. FindJObj GUI - display container hierarchy The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....
  5. UISplitPane UISplitPane was recently chosen as Matlab Central's Pick of the Week. Here I detail its use of some undocumented Matlab features....
  6. Additional uicontrol tooltip hacks Matlab's uicontrol tooltips have several limitations that can be overcome using the control's underlying Java object....

Tags: , , , , , , ,

PoorSo-soHelpfulVery helpfulExcellent! (No Ratings Yet)
Loading ... Loading ...
Bookmark and Share Print Print

7 Responses to “Continuous slider callback”

  1. Dani Dani says:

    Hi,

    another functionality that would benefit from continuous callback is figure resizing. For example, it would be useful to allow for figure resizing, but only to a certain minimum size. Since ResizeFcn callback is only evaluated once the mouse button is released, ‘jumping’ from, for example, very small resized windows to the desired minimum size cannot be avoided.

    The other problem with figure sizes and resizing is that Matlab only knows the original screen size. This leads problems if the screen resolution has been changed on the way, for example due to connection to a projector.

    Can these be solved with some java magic?

    Dani

  2. Yair Altman Yair Altman says:

    @Dani - Unfortunately, the window resizing event is only propagated upon mouse release. There’s probably a Java workaround, but I don’t know it. You can use the three separate methods shown above, but you’ll see the same result:

    % 1. Callbacks:
    jFrame = get(gcf,'JavaFrame');
    jhFrame = handle(jFrame.fFigureClient.getWindow, 'CallbackProperties');
    set(jhFrame,'ComponentResizedCallback',@myCallback);
     
    % 2. Event listener:
    hListener = handle.listener(gcf,'ResizeEvent',@myCallback);
     
    % 3. Property listener:
    hFig = handle(gcf);
    hProp = findprop(hFig,'Position');
    hListener = handle.listener(hFig,hProp,'PropertyPostSet',@myCallback);
  3. Matt Whitaker Matt Whitaker says:

    For the screensize issue try:

    import java.awt.*;
    toolkit = Toolkit.getDefaultToolkit();
    scrnsize = toolkit.getScreenSize();
    h= scrnsize.getHeight;
    w =scrnsize.getWidth;

    Not sure if there is some kind of listener for changes in that

  4. Yair Altman Yair Altman says:

    The screensize can also be gotten via pure Matlab:

    pos = get(0,'ScreenSize');

    Note that if you have multiple concurrent monitors this gets a bit trickier.

  5. Dani Dani says:

    You guys are worth gold! (German proverb, not sure it exists in English)

    @Yair - thanks, good to know it cannot be done.

    @Matt - excellent, works and detects changes in screen resolution.

  6. Dani Dani says:

    @Yair - unfortunately

    get(0,'ScreenSize');

    does not (reliably) return updated screen resolution info in cases where the resolution was changed during a running MATLAB session. However, now you got me worried regarding multiple monitors and I had a look at

    get(0,'MonitorPositions')

    which does seem to return correctly updated info.

  7. Yair Altman Yair Altman says:

    To be precise, I didn’t say it cannot be done, only that I personally have not found a way to do it. I actually tend to think it can be done somehow.

Leave a Reply


Wrap code fragments inside <pre lang="matlab"> tags, like this:

   <pre lang="matlab">
   a = magic(3);
   sum(a)
   </pre>