- Undocumented Matlab - https://undocumentedmatlab.com -

Continuous slider callback

Posted By Yair Altman On February 8, 2010 | 56 Comments

Every few months, a CSSM forum reader asks how to set up a continuously-invoked slider callback: Matlab’s slider uicontrol [1] 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 [2], 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 [3], 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 [4] but JScrollBars [5], have an AdjustmentValueChangedCallback property that is useful for our purposes and is accessible using the FindJObj utility [6]. Simply download FindJObj from the File Exchange [7], 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);
setappdata(hSlider,'sliderListener',hListener);  % this is important - read below

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

In this case, hScrollpanel is merely a handle to a panel in Matlab’s imscrollpanel code. You can use any Matlab control to store the listener handle, including hSlider itself, which would be simplest. It doesn’t matter where or how exactly you store hListener, since you will not use it directly in your program. The important thing is just to store it *anywhere*, so that it remains in persistent (heap) memory. As long as the reference handle is “alive”, the listener will keep working. This is explained here [8].
Addedndum 2014-08-20: In R2014a the event name has changed from ActionEvent to ContinuousValueChange. Also, handle.listener will not work in the upcoming HG2. Therefore, it would be best to use the following code snippet instead:

try    % R2013b and older
   addlistener(hSlider,'ActionEvent',@myCallbackFcn);
catch  % R2014a and newer
   addlistener(hSlider,'ContinuousValueChange',@myCallbackFcn);
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');
try    % R2014b and newer
   % hProp is a matlab.graphics.internal.GraphicsMetaProperty object
   addlistener(hSlider,hProp,'PostSet',@myCbFcn);
catch  % R2014a and older
   % hProp is a schema.prop object
   hListener = handle.listener(hhSlider,hProp,'PropertyPostSet',@myCbFcn);
   setappdata(hSlider,'sliderListener',hListener);  % this is important - read above
end

In addition to ‘PostSet’, we could also listen on ‘PreSet’, which is triggered immediately before the property is modified. There are also corresponding ‘*Get’ options.
Do you know of any other way to achieve continuous callbacks? If so, I would be delighted to hear in the comments section below.

Categories: GUI, Java, Listeners, Medium risk of breaking in future versions, UI controls


56 Comments (Open | Close)

56 Comments To "Continuous slider callback"

#1 Comment By Dani On February 18, 2010 @ 08:55

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 Comment By Yair Altman On February 18, 2010 @ 09:45

@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 Comment By Matt Whitaker On February 18, 2010 @ 11:40

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 Comment By Yair Altman On February 18, 2010 @ 16:21

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 Comment By Dani On February 19, 2010 @ 01:49

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 Comment By Dani On February 19, 2010 @ 02:04

@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 Comment By Yair Altman On February 19, 2010 @ 02:21

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.

#8 Comment By Gerrit On March 30, 2010 @ 02:08

Hi,
I recently implemented a GUI with AdjustmentValueChangedCallback for a JTree’s vertical slider. The acquired values were used to update the slider position of one or more dependent listboxes. (The tree shows a directory with all subdirectories and files, the listboxes only display one file type each, but in the same rows as they are in the tree.)
Problem is that if the JTree’s slider position changed fast (e.g. via mouse wheel usage), strings inside the listboxes are not in their correct positions or displayed twice.

mylb1 = uicontrol('Style','listbox');
mylb2 = uicontrol('Style','listbox');
mytree = uitree;
myjtree = mytree.getTree;
%
myjscrollpane = findjobj(gcf,'property',{'VerticalScrollBarPolicy',20});
dummy = myjscrollpane.getComponents;
myjslider = dummy(2);
%
mylbscrollpanes = findjobj(gcf,'property',{'VerticalScrollBarPolicy',22});
dummy1 = mylbscrollpanes(1).getComponents;
dummy2 = mylbscrollpanes(2).getComponents;
mylb1slider = dummy1(2);
mylb2slider = dummy2(2);
%
set(myjslider,'AdjustmentValueChangedCallback',{@myAdjustFcn});
set(myjtree,'MousePressedCallback',{@myMouseFcn},...
'TreeExpandedCallback',{@myExpFcn},...
'TreeCollapsedCallback',{@myColFcn});

The listbox strings are updated via “myExpFcn” and “myColFcn” and contain correct data.
“myAdjustFcn” gets myjslider’s “Maximum” and “Value” and sets them in mylb1slider and mylb2slider respectively. I noticed the callback is sometimes called twice (expand, collapse) or three times (mouse wheel) and does not update the listbox sliders correctly in the first run (seems to appear only within expand)…

Does anyone know of this display bug/problem/whatever?

#9 Comment By Janos Marki On April 10, 2010 @ 17:45

Epic fail.

I tried all three methods, none worked for me. I am using a GUIDE created function, and to start with, I have the problem that I have no idea where the listeners should be created (openingFCN, main function or outside of function?). However, if I would be past that, at the next step, I don’t understand what input parameters are given when a function is referenced simply as @myCbFcn. I have gotten as far as getting this function executed (when moving it out into a separate file as opposed to having it in the main GUI file), but then I just get crap from schema.prop and Java gibberish instead of getting the handles through these calls. Sorry, I just don’t understand…

I’ll try to be more specific. In this example:

hListener = handle.listener(hhSlider,hProp,'PropertyPostSet',@myCbFcn);

What input arguments are passed to @myCbFcn??? I thought it would be hObject, EventData, handles, but it really is not…

Thanks!
Janos

#10 Comment By Janos Marki On April 11, 2010 @ 03:29

Trying to break it down a little more. Trying to put it into fnname_OpeningFcn, nothing happens on the slider movement event:

function untitled_OpeningFcn(hObject, eventdata, handles, varargin)

% Choose default command line output for untitled
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

set(handles.text1,'String',get(handles.slider1,'Value'))

handle.listener(handles.slider1,'ActionEvent',@updatetextbox);
%addlistener(handles.slider1,'ActionEvent',@updatetextbox); %using this variation does not work, either

And updatetextbox looks like this in a separate file (i.e. once it registers a slide movement, execution should jump inside updatetextbox and give me keyboard access, so I can at least see what inputs it got – but it does not happen (probably because I defined the listener inside, at the OpeningFcn level?).

function updatetextbox(varargin)
keyboard
slidval=get(handles.slider1,'Value');
set(handles.text1,'String',num2str(slidval));

If I define the listener in the main function, then there is a problem – it runs through a lot of times. I can catch one where the figure is plotted already (where varargout already exists), grab the handle, add the listener… and nothing happens (sigh).:


function varargout = untitled(varargin)
% UNTITLED M-file for untitled.fig
%  *** standard comment section ***
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help untitled
% Last Modified by GUIDE v2.5 11-Apr-2010 01:31:27

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @untitled_OpeningFcn, ...
                   'gui_OutputFcn',  @untitled_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% *** ADDED MY BIT HERE!!! ***
if exist('varargout')==1       %stopping main function once figure is up
   handles=guidata(varargout{1});      %grabbing the handles structure
   handle.listener(handles.slider1,'ActionEvent',@updatetextbox);  %adding listener
end

In this case, I think as the whole namespace disappears once this instance of the function runs through, the listener disappears with it, too.
(I’ll post this now, and continue in the next)

#11 Comment By Janos Marki On April 11, 2010 @ 03:57

So in the post above, I tried implementing handle.listener at the Opening_Fcn and the main function level. Last option is outside the function, at the command prompt level. And this is what I do…

>> ni=untitled
ni =
  173.0035

>> handles=guidata(ni)
handles = 
    figure1: 173.0035
      text1: 1.0059
    slider1: 174.0031
     output: 173.0035

>> handle.listener(handles.slider1,'ActionEvent',@updatetextbox);

% *** Now try moving the slider ***
% YES, IT WORKS, we get to updatetextbox...
% So what arguments did updatetextbox get?

K>> varargin
varargin = 
    [1x1 uicontrol]    [1x1 handle.EventData]

Right, great news. So to do this, now I need a callback function of this form:

function updatetextbox(hObject, eventdata, handles)
handles=guidata(hObject);
slidval=get(handles.slider1,'Value');
set(handles.text1,'String',num2str(slidval));
 

And this finally works!!

Phew. Now, on to the “interesting” question. How can I “package” this up into the GUI itself (which was, as said, created by GUIDE, so I can’t just put the listener line after the creation of a uicontrol object. Using a script, which launches the GUI, then contains the above commands in chronographical order?

In fact, question no. 2:
I chose GUIDE because the fact of not having to set uicontrol object positions and sizes by coding but graphically is very easy and fast for me. Was that silly, and is that the reason for all the above suffering? (i.e. once one needs something past very basic funtionality – e.g. continuous slider callback – GUIDE is NOT the way to go?

In case there WAS anyone who followed through my “troubleshooting”, thanks, any further advice for a noob like me highly welcome.

Cheers,
Janos
Last bit of info:
I based this on the function untitled.m (and the associated saved untitled.fig) from here:
[15]

Which is supposed to be a solution for exactly this problem. On its own, it did not work, and that is when I tried implementing your solutions (though it is supposed to be what I am looking for, i.e. continuous slider callback from within a GUIDE-created GUI)

#12 Comment By Yair Altman On April 11, 2010 @ 04:43

@Janos – hListener=handle.listener requires you to store the returned hListener handle somewhere – the listener only works as long as its handle is stored somewhere. A good place to store this listener is in the target object’s ApplicationData, using the built-in setappdata function:

hListener=handle.listener(handles.slider1,'ActionEvent',@updatetextbox);
setappdata(handles.slider1,'myListener',hListener);

You can do this in your main code – no need to use the Command Window. The reason it worked for you in the Command Window is that the handle.listener result was kept in the ans variable, so as long as ans was not changed the listener worked.

#13 Comment By Janos Marki On April 11, 2010 @ 05:21

@Yair:
I see, makes sense! I put your 2 lines of code into my function’s OpeningFcn, the Callback function back at the bottom of the main GUI .m-file and it all works now, thanks! Sorry for polluting the thread with such a looooong entry! 🙂

#14 Comment By Yair Altman On April 11, 2010 @ 05:25

Glad to help – that’s what I’m here for…

The most difficult questions sometimes have very simple solutions, as in this case

#15 Comment By Janos Marki On April 11, 2010 @ 15:41

Thanks again, I even ended up using the “Donate” button. I don’t do that often, so you can be sure of seeing me here again!

#16 Comment By Yair Altman On April 11, 2010 @ 22:13

Much obliged, Janos 🙂

Positive feedback such as yours is very important for me when I have to explain to my family why I spend so much time on this website, for no apparent benefit…

#17 Comment By Cemil Kirbas On June 1, 2010 @ 11:57

Hi,

I created a GUI using guide with two sliders to adjust image window and level. When I use setappdata to my slider object a new figure is created when I started to use the slider. My image is displayed in the new figure instead of my current GUI figure. Any idea why this is happening. Your help is appreciated. Thanks.

Cemil

#18 Comment By Yair Altman On June 1, 2010 @ 12:06

@Cemil – this could be due to several reasons: My bet is that your figure has a hidden handle (HandleVisibility=’off’) and in your callback function you are using the gcf function or some other similar function that creates a new figure in such cases. Instead, use the actual figure handle that is available in your handles struct and ensure that you pass this handle to every function that could possibly need it (axes etc.).

#19 Comment By Cemil Kirbas On June 2, 2010 @ 06:59

Thank you very much Yair. That was a great help. I changed HandleVisibility of the figure from its default value ‘callback’ to ‘on’ and the problem is solved. I appreciate your help.

Best regards,

Cemil.

#20 Comment By Florin On March 7, 2011 @ 17:59

Hi,

I have been reading this post, but I still have a problem. I am reading and a .tif file and display slices of it with imagesc. I am trying to continuously update this images when moving the slider. I have the same problem as Cemil : a new windows appears and the imagescs are updated in that new figure. As soon as I release the mouse button the intended figure inside my GUI is also updated. I checked the HandleVisibility parameter. I also tried to set the handle with

figure(get(handles.axes1,'Parent'));

Any suggestions for me, pls ?

Thank you.
Florin

#21 Comment By Yair Altman On March 8, 2011 @ 00:36

@Florin – you probably have the same problem as Cemil and the solution is similar. In your slider callback, instead of using a simple imagesc, directly specify the parent axes:

imagesc('Parent',handles.axes1, 'XData',xdata, 'YData',ydata, ...);

#22 Comment By Florin On March 8, 2011 @ 16:17

Yair,

Thank you for your quick reply. That worked.
Hope you can maintain this site for a long time.
I wish you all the best.

Regards,
Florin

#23 Comment By Jonas On April 7, 2011 @ 02:56

Dear Yair
Your blog is just wonderful and helps me a lot these days in getting somewhere with my thesis. Thank your for your good work!

Regarding the continuous slider callback, I wonder what the difference between

hListener = handle.listener(handles.mySlider,'ActionEvent',@mySliderMoved);
setappdata(handles.mySlider,'mySliderListener',hListener); 

and

hListener = addlistener(handles.mySlider, 'ActionEvent', @mySliderMoved);

exactly is…?

Best,
Jonas

PS. looking forward to your relevations of 2011a – coming tomorrow 🙂

#24 Comment By Yair Altman On April 7, 2011 @ 03:36

@Jonas – these are essentially the same, except that addlistener adds the listener in a hidden property called Listeners__, rather than in the similarly-hidden ApplicationData property (which is what setappdata does).

>> get(handles.mySlider, 'Listeners__')
ans =
	handle.listener

The actual place where the listener is stored does not matter. It is only important to store listeners together with the listened object, so that they both have exactly the same life-span. Both of these methods do that, by storing the listener in one of the object handle’s properties.

The source code for addlistener is not available in the latest Matlab releases (it’s implemented as an internal function), but it is available and inspectable in Matlab releases up to 2008 (e.g., C:\Program Files\Matlab\R2008a\toolbox\matlab\uitools\private\addlistener.m). This source code is not long (only ~30 code lines) and it’s interesting, so I recommend looking at it.

#25 Comment By Jonas On April 21, 2011 @ 07:09

A short update form my side – as I now run on R2011a.

I used to run a listener as proposed (R2010a/b) in the post the following way:

lh = addlistener(sliderhandle, 'ActionEvent',@MyCallback);

The new Version of Matlab (R2011a) gives me a warning that I should not use this method anymore but rather use: a “ContinuousValueChange” Event.
So I end up with:

lh = addlistener(sliderhandle, 'ContinuousValueChange',@MyCallback);

which works pretty smooth. However, besides of that one-time-console-warning I have not found any documented information about this “ContinuousValueChange”-event or other hidden events…

Best, Jonas

#26 Pingback By Matlab continuous slider callback « Desperate Engineers Blog On May 4, 2011 @ 01:53

[…] ([uicontrol('Style','slider', …]) in a MATLAB GUI. Thanks to the posting of Yair Altman on this topic (on his awesome Undocumented Matlab Blog which you shoudl definitely check out), I had no problem […]

#27 Comment By Elise On May 27, 2011 @ 17:14

Thanks! Handle.listener worked great!

#28 Comment By claus On January 26, 2012 @ 09:34

Hi, thank you for your help!

I turned my sliders into continuous just by adding two simple mods:

first, add the following 2 lines to your xxxxxx_OpeningFcn:

hListener=addlistener(handles.sliderN, 'ContinuousValueChange', @sliderN_Callback);
setappdata(handles.sliderN,'myListener',hListener);

then, add the following 3 lines to your sliderN_Callback:

if ~(exist('handles','var'))
     handles=guidata(hObject);
end

It works like a charm!

Thank you!

#29 Comment By John On February 18, 2012 @ 08:00

Hi guys,

i just wanted to add my solution to the continuous slider problem, which seems to be the simpliest/easiest way to understand (imho):

1. Create the control:

    myslider = uicontrol(topWindowHandle, ...
        'Style', 'slider', ...
        'Min', 0, 'Max', 100, ...
        'Value', 25, ...
        'SliderStep', [0.05 0.2], ...
        'Position', [60 100 350 18]);

2. Add a listener to the Value-property:

addlistener(handle(myslider), 'Value', 'PostSet', @slider_callback);

3. Implement the slider-callback-function:

    function slider_callback(hObject, eventdata)
        obj = get(eventdata, 'AffectedObject');
        val = get(obj, 'Value');
        display(val);
    end

Now, val contains the actual slider value, because the AffectedObject-property holds the desired slider control, from which we can obtain our slider-value.

Greetings

John

#30 Comment By Alfonso On March 21, 2012 @ 00:09

This is awesome!
Thank you!

#31 Pingback By Waterloo graphics | Undocumented Matlab On November 28, 2012 @ 11:16

[…] One of Matlab’s limitations is the quality of its 2D graphics. Plots are more pixellated and less interactive than some might expect in a modern programming environment. […]

#32 Pingback By Customizing figure toolbar background | Undocumented Matlab On February 20, 2013 @ 11:02

[…] For the slider I used a javax.swing.JSlider having a continuous-movement callback […]

#33 Comment By Jing On April 16, 2013 @ 18:44

Hi, Thank you for posting this nice solution. But I have some troubles using it in GUIDE.

Everything works out fine except that the callback function on mySlider is always called twice!
The first time, hObject passed from callback function is the slider itself; The second time the hObject = uicontrol.

I’m trying to pass handles in this callback function, but in the case when hObject = uicontrol, the data in handles never got updated. This is the real problem that troubles me.

Please help, Thank you.

#34 Comment By Yair Altman On April 17, 2013 @ 00:11

@Jing – you could add the following at the top of your calback function:

if ~isjava(hObject),  return;  end

#35 Comment By Jing On April 29, 2013 @ 09:46

@Yair – Thank you so much. Sorry for my late late reply…

#36 Comment By DSN On September 23, 2013 @ 03:47

Thanks a lot Yair :). clean and neat solutions.

#37 Comment By Aya On October 24, 2013 @ 22:10

Yair,

What exactly is ‘hScrollpanel’ in your “Using an event listener” option? I am trying to replicate your code, but I do not know where you got this ‘hScrollpanel’ from..thanks.

#38 Comment By Yair Altman On October 24, 2013 @ 22:40

@Aya – hScrollpanel is simply part of Matlab’s imscrollpanel code that I presented to show how the concept is being used. It is merely a handle to a panel. You can use any Matlab control to store the listener handle, including hSlider itself, which would be simplest:

setappdata(hSlider,'sliderListener',hListener)

It doesn’t matter where or how exactly you store hListener, since you will not use it directly in your program. The important thing is just to store it *anywhere*, so that it remains in persistent (heap) memory. As long as the reference handle is “alive”, the listener will keep working. This was explained [16].

#39 Comment By Young Pink On May 15, 2014 @ 20:16

Hi,
From your blog, I learned a lot. What you are talking about in this blog is event listener within a gui . however, if a listener is set to slider in the main gui, update text in the child gui ​​in the response function of the listener , how to do it? I’m troubled.
In the response function ,obtaining handle of the child: handles = guihandles (sub); then use the set function, but doesn’t work, why? Moreover, the slider in the main gui has listener response function and callback function , when dragging with the mouse, how these two functions work together?
Please help me ,thanks.

#40 Comment By Yair Altman On May 18, 2014 @ 17:06

@Young – I suggest that you read and experiment with Matt Fig’s [17] to understand how Matlab GUI callbacks work.

#41 Comment By Bill Doss On August 20, 2014 @ 06:58

What are the arguments passed into the ‘AdjustmentValueChangedCallback’ function? I saw them mentioned somewhere, here on this site or in your book, but I can’t seem to find them again.

Thanks so much,
Bill

#42 Comment By Yair Altman On August 20, 2014 @ 07:29

@Bill – it’s exactly like any other [18]. It accepts an object reference as first input arg, followed by an eventData object (that includes information on the triggered event). You can also specify additional extra parameters. See the official docpage in the previous link for details. Also read my description of [19].

#43 Comment By Bill Doss On August 20, 2014 @ 09:45

@Yair Thanks … I noticed some quirky behavior and I don’t know if it’s something I forgot to do or just what is going on.

Using the following simple test:

abc.m:

figure(1); clf
hs = uicontrol('Style', 'slider', 'Units', 'pixels', ...
    'Position', [20 74 240 24], 'Tag', 'my_slider', ...
    'Min', 1, 'Max', 44, 'SliderStep', [1/43 10/43], 'Value', 1);
hj = findjobj(hs);
hj.AdjustmentValueChangedCallback = @def;

def.m

function def(hObject, eventdata)
v = get(hObject, 'Value'); % Or get(eventdata, 'Value')
fprintf('Value from input argument is %g\n', v);
h = findobj('Tag', 'my_slider');
fprintf('Value from finding Matlab handle is %g\n', get(h, 'Value'));
end

I get different values for the slider depending on how I try to get it:

>> abc
Value from input argument is -900000
Value from finding Matlab handle is 2
Value from input argument is -800000
Value from finding Matlab handle is 3
Value from input argument is -700000
Value from finding Matlab handle is 4

I also noticed that the AdjustmentValueChangedCallback was called multiple times when I clicked inside the slider or moved the slider button.

Am I missing something?

Again thanks a bunch!!
Bill

#44 Comment By Yair Altman On August 20, 2014 @ 13:39

@Bill – Java sliders have different model values for the slider than Matlab. Since you have my book, look at page 418. You simply need to convert between the increment and min/max values using a simple linear transformation formula. But I really don’t understand why you’d want to do this if you can simply listen to the event at the Matlab level using the addlistener technique that I explain in this article.

#45 Comment By Bill Doss On August 21, 2014 @ 09:04

@Yair … I’ll try that approach.

Thanks again.
Bill

#46 Comment By Amindo On July 15, 2015 @ 02:13

I am new to matlab and I need your help please.

I have several subplots in a collum then I create an horizontal slider to see better some parts of the subplots data. meanwhile I create a patch to be able to select a region (selecting band) of the subplots and extract the data. My problem is that I want to drag the selecting band(as I drag the mouse it increase or decrease de selection area) and by doing that I need that the slider adjust its position, even more important I need to be able to adjust the plot horizontally as the selection region increase to the right (like if I press the slider button) or to the left.

Basically when I increase the selection band to the right or to the left I need that plot behaves like I was pressing the slider buttons to the right or to the left.

Iam lost about how to perform this can anyone help showing me some possible code to achieve this?

#47 Comment By Yair Altman On July 15, 2015 @ 03:30

@Amindo – perhaps [20] on the File Exchange will help you. If not, then contact me offline (by email) for a a consulting proposal.

#48 Comment By daniel On July 20, 2015 @ 07:32

Well, for some reason TMW has elliminated the ‘ContinuousValueChange’ event for the sliders in R2015a, an it will not work in this version…. Even worse, there is no comparable event that one could think of using.

That’s a pity, I had many code based in this approach, which is know perfectly useless :-/

#49 Comment By Yair Altman On July 20, 2015 @ 11:26

@Daniel – the ContinuousValueChange event still exists. It is simply hidden, but should be fully functional:

addlistener(hSlider, 'ContinuousValueChange', @(h,e)disp('Changing!'))

Other hidden events of sliders include: Action, KeyPress, KeyRelease, LocationChanged, SizeChanged, ButtonDown, Reset

Additional information: [21]

#50 Comment By daniel On July 21, 2015 @ 01:58

Yes! Fewh, my code will still works with some changes.

Actually, my code was written defensively, checking explicitly that ‘ContinuousValueChange’ is in the list of events in a handle… the result is that the code refuses to create the listener to an apparently non available-event.

Thanks for pointing me to your list of events in HG2: it is the only source of information I can use to harness events!

… I really wonder why TMW has hidden these events: I don’t see any advantage, and it makes life much harder…

#51 Comment By Yair Altman On July 21, 2015 @ 02:10

@Daniel – this is one of the reasons that I use try/catch rather than if/else

#52 Comment By Armindo On July 21, 2015 @ 09:21

Thank you for the help.
I think that I can solve the problem if I can converte the x coordenate obtained thru the get(gca’CurrentPoint’) to the slider scale. There is a easy way to do this?

kind regards

#53 Comment By SeifEddine On December 30, 2015 @ 09:00

Matlab R2015a:

hProp = findprop(hSlider,'Value');
hListener = addlistener(hSlider,hProp,'PostSet',@myCbFcn);
setappdata(hSlider,'sliderListener',hListener);

Cordially.

#54 Comment By Yair Altman On December 30, 2015 @ 09:57

Thanks Seif – I clarified the post text accordingly.

#55 Comment By Felix On February 23, 2017 @ 18:14

Hello,

I have some performance issues when using the addlistener in addition to WindowButtonMotionFcn:

function temp
   F = figure();
   set(F,'WindowButtonMotionFcn',@Cursor);
   H = uicontrol(F,'Style','slider');
   addlistener(H, 'Value', 'PostSet',@getSliderValue);
end
function getSliderValue(hObj,event)
   get(event.AffectedObject,'Value')
end
function Cursor(hObj,event)
   disp('move')
end

Is there a way to suppress the WindowButtonMotionFcn of the figure during the continuous slider callback? I tried using the WindowButtonDownFcn/WindowButtonUpFcn to remove/add the WindowButtonMotionFcn, but WindowButtonDownFcn nor ButtonDownFcn is called when the slider property ‘Enable’ is set ‘on’. Using ‘inactive’ first would a require a second click to tell Matlab to drag the slider…

function temp
   F = figure();
   set(F,'WindowButtonMotionFcn',@Cursor);
   set(F,'WindowButtonDownFcn',@ButtonDown);
   set(F,'WindowButtonUpFcn',@ButtonUp);
   H = uicontrol(F,'Style','slider');
   addlistener(H, 'Value', 'PostSet',@getSliderValue);
end
function getSliderValue(hObj,event)
   get(event.AffectedObject,'Value')
end
function Cursor(hObj,event)
   disp('move')
end
function ButtonDown(hObj,event)
   set(gcf,'WindowButtonMotionFcn',[]);
end
function ButtonUp(hObj,event)
   set(gcf,'WindowButtonMotionFcn',@Cursor);
end

Thanks, Felix

#56 Comment By Felix On February 23, 2017 @ 18:18

May add a listener to ButtonDownFcn/ButtonUpFcn ? I tried various events but only got errors like:

Event 'ButtonDownFcn' is not defined for class
'matlab.ui.control.UIControl'.

Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/continuous-slider-callback

URLs in this post:

[1] slider uicontrol: http://blinkdagger.com/matlab/matlab-gui-tutorial-slider/

[2] yesterday: https://www.mathworks.com/matlabcentral/newsreader/view_thread/272224

[3] article: http://undocumentedmatlab.com/blog/uicontrol-callbacks/

[4] JSliders: http://java.sun.com/docs/books/tutorial/uiswing/components/slider.html

[5] JScrollBars: http://java.sun.com/docs/books/tutorial/uiswing/components/scrollpane.html#operation

[6] FindJObj utility: http://undocumentedmatlab.com/blog/findjobj-find-underlying-java-object/

[7] File Exchange: http://www.mathworks.com/matlabcentral/fileexchange/14317

[8] here: http://undocumentedmatlab.com/blog/udd-events-and-listeners/#listener

[9] Controlling callback re-entrancy : https://undocumentedmatlab.com/articles/controlling-callback-re-entrancy

[10] Callback functions performance : https://undocumentedmatlab.com/articles/callback-functions-performance

[11] Property value change listeners : https://undocumentedmatlab.com/articles/property-value-change-listeners

[12] Setting axes tick labels format : https://undocumentedmatlab.com/articles/setting-axes-tick-labels-format

[13] UDD Events and Listeners : https://undocumentedmatlab.com/articles/udd-events-and-listeners

[14] Inactive Control Tooltips & Event Chaining : https://undocumentedmatlab.com/articles/inactive-control-tooltips-event-chaining

[15] : http://www.mathworks.com/support/solutions/en/data/1-3SR0YI/index.html?product=ML&solution=1-3SR0YI

[16] : https://undocumentedmatlab.com/blog/udd-events-and-listeners/#listener

[17] : http://www.mathworks.com/matlabcentral/fileexchange/24861-41-complete-gui-examples

[18] : http://www.mathworks.com/help/matlab/creating_plots/function-handle-callbacks.html

[19] : https://undocumentedmatlab.com/blog/uicontrol-callbacks

[20] : http://www.mathworks.com/matlabcentral/fileexchange/14984-scrollplot-scrollable-x-y-axes

[21] : https://undocumentedmatlab.com/blog/undocumented-hg2-graphics-events

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.