passing uicontrol objects to uicontrol callbacks

I have three sliders that are in the same position, and based on a radio button selection, I'd like to make one of the three appear at one time.
I've tried to do this by making only one visible at any point in time. I've tried to accomplish this by passing the slider uicomponents to the respective callback functions of the radio buttons, so that i might make one visible and the other two invisible.
Essentially,
%%%%%Make slider objects at same position%%%%%%
p=uipanel;
sliderterminal = uicontrol(p,'Style','slider');
sliderinitial = uicontrol(p,'Style','slider');
sliderthreshold = uicontrol(p,'Style','slider');
%%%%%controlling radio buttons%%%%%%
bg = uibuttonggroup(p);
rinitial = uicontrol(bg,'Style','radiobutton','Callback',@initialcutoff)
rterminal = uicontrol(bg,'Style','radiobutton','Callback',@terminalcutoff)
rthreshold = uicontrol(bg,'Style','radiobutton','Callback',@thresholdindex)
%%%%%%Callback Functions%%%%%
function initialcutoff(sliderthreshold,sliderinitial,sliderterminal)
sliderterminal.Visible='off';
sliderthreshold.Visible='off';
sliderinitial.Visible='on';
end
function terminalcutoff(sliderthreshold,sliderinitial,sliderterminal)
sliderinitial.Visible='off';
sliderthreshold.Visible='off';
sliderterminal.Visible='on';
end
function thresholdindex(sliderthreshold,sliderinitial,sliderterminal)
sliderinitial.Visible='off';
sliderterminal.Visible='off';
sliderthreshold.Visible='on';
end
When the callback functions are accessed the desired uicontrol objects are not passed in from the base workspace. If anybody could help me with this issue I would greatly appreciate insight. Please let me know if I'm going about this all wrong.
PS - I didn't add the position information for the uicomponents as i figured added a lot of extraneous information isn't too good of an idea.

 Accepted Answer

There are several ways to pass data/handles between callbacks. For some in depth information you can check here.
I can see 2 problems with your code.
  1. Callback functions in matlab always have atleast 2 inputs (3 if working with guide). Those are provided by matlab and you do not need to specify them.
function mycallback(hObj,event,handles)
%code
end
  1. When you want to pass additional arguments to a callback function you need to tell matlab which ones.
rinitial = uicontrol(bg,'Style','radiobutton','Callback',{@initialcutoff,sliderterminal,sliderinitial,sliderthreshold})
But remember the first arguments of your callback function are reserved.
Now about a possible solution to your question: I would start storing all my handles in a struct.
handles.p=uipanel;
%%%%%controlling radio buttons%%%%%%
handles.bg = uibuttongroup(handles.p);
handles.rinitial = uicontrol(handles.bg,'Style','radiobutton','Callback',{@radiobutton_callback},'position',[20 40 20 20]);
handles.rterminal = uicontrol(handles.bg,'Style','radiobutton','Callback',{@radiobutton_callback},'position',[20 60 20 20]);
handles.rthreshold = uicontrol(handles.bg,'Style','radiobutton','Callback',{@radiobutton_callback},'position',[20 80 20 20]);
handles.sliderterminal = uicontrol(handles.p,'Style','slider','position',[20 200 100 20],'visible','off');
handles.sliderinitial = uicontrol(handles.p,'Style','slider','position',[20 200 120 20],'visible','off');
handles.sliderthreshold = uicontrol(handles.p,'Style','slider','position',[20 200 110 20],'visible','off');
guidata(handles.p,handles)
Next i would write one callback function for your radiobutton and pass your handles struct:
function radiobutton_callback(hObj,~)
handles=guidata(hObj);
if handles.rinitial.Value ==1
handles.sliderterminal.Visible='off';
handles.sliderthreshold.Visible='off';
handles.sliderinitial.Visible='on';
elseif handles.rterminal.Value ==1
handles.sliderterminal.Visible='on';
handles.sliderthreshold.Visible='off';
handles.sliderinitial.Visible='off';
else
handles.sliderterminal.Visible='off';
handles.sliderthreshold.Visible='on';
handles.sliderinitial.Visible='off';
end
end

6 Comments

Thank you so much for explaining this all to me! I really appreciate it Dennis!
If it wouldn't bother you too much I'd like to ask a couple questions.
I was wondering how exactly that hObj input that the callback function reserves really works. What exactly does it point to when you use it? What are the rules that matlab follow to pick out what structure that points to?
Thanks for all the help you've given!
If it's a matter of just becoming more well versed with computer science in order to better understand the documentation let me know, as i do not want to waste anybodys' time.
Glad i can help :)
The hObj is the handle of your calling Object, a minimalistic example how to use it:
uicontrol('style','pushbutton','callback',@simple_cb)
uicontrol('style','pushbutton','position',[20 40 60 20],'callback',@simple_cb)
function simple_cb(hObj,~)
hObj.String = 'Button';
end
We are creating 2 buttons with the same callback. The callback changes the string of the calling object -> the button pushed.
You can aswell compare it with other handles, if you want to find out which object issues a callback. As example another approach to slider control via radiobutton (first part is mostly the same, just renamed the callbacks):
handles.p=uipanel;
%%%%%controlling radio buttons%%%%%%
handles.bg = uibuttongroup(handles.p);
handles.rinitial = uicontrol(handles.bg,'Style','radiobutton','Callback',{@radiobutton_callback2},'position',[20 40 20 20]);
handles.rterminal = uicontrol(handles.bg,'Style','radiobutton','Callback',{@radiobutton_callback2},'position',[20 60 20 20]);
handles.rthreshold = uicontrol(handles.bg,'Style','radiobutton','Callback',{@radiobutton_callback2},'position',[20 80 20 20]);
handles.sliderterminal = uicontrol(handles.p,'Style','slider','position',[20 200 100 20],'visible','off');
handles.sliderinitial = uicontrol(handles.p,'Style','slider','position',[20 200 120 20],'visible','off');
handles.sliderthreshold = uicontrol(handles.p,'Style','slider','position',[20 200 110 20],'visible','off');
guidata(handles.p,handles)
function radiobutton_callback2(hObj,~)
handles=guidata(hObj);
switch hObj
case handles.rinitial
handles.sliderterminal.Visible='off';
handles.sliderthreshold.Visible='off';
handles.sliderinitial.Visible='on';
case handles.rterminal
handles.sliderterminal.Visible='on';
handles.sliderthreshold.Visible='off';
handles.sliderinitial.Visible='off';
case handles.rthreshold
handles.sliderterminal.Visible='off';
handles.sliderthreshold.Visible='on';
handles.sliderinitial.Visible='off';
end
end
Here we used a switch statement to compare our hObj to our radiobutton handles.
I started learning matlab not too long ago and i appreciate the practice.
Thanks so much for taking the time to explain this to me!
I've just got one more question -
It seems to me that when the guidata function is called a new object is created. I am thinking in terms of workspaces. I see a new object created in a workspace other than the base workspace. How does the guiobject in the base workspace inherit the changes you made to them in the function?
Is there an aspect of computer science I have to understand first? Is this simply the nature of the guidata function?
When I look at the guidata documentation, It says that use of guidata can do the following
" [to manipulate your data,] Get
a copy of the data with the command
data = guidata(object_handle).
Make the desired changes to data.
Save the changed version of data with the command
guidata(object_handle,data). ... "
It then says
" ... You can access the data from within a local function callback routine using the component's handle"
Does this happen automatically or is there something that still needs to be completed?
We reached a point where i can't tell you for sure, because i think i know how it works - but in reality i do not know.
I don't think that guidata creates a new object. I imagine it attaches a property to an existing object (the figure). The main purpose of guidata() is to store/retrieve variables in different function workspaces. If you change the variables in one function, the variable stored in your guiobject will not change. To save your changes you need to call guidata(object_handle,mydata). This will store mydata with the parent figure of your object. However it will overwrite any existing variable. To prevent this from happening you can use a struct.
A small example: We have a GUI with our handles stored with guidata and now want to add some data from a complex calculation to use them in another function.
function simple_callback(hObj,~)
handles=guidata(hObj); %retrieve whatever is stored with guidata
myvalue=1:5; %complex calculation
handles.myvalue=myvalue; %append myvalue to handles struct
guidata(hObj,handles) %save handles
end
Now we can use guidata() to use handles.myvalue in another function.
Thank you so much for all your help I think I understand now! This stranger really appreciates it!
Best wishes to you!

Sign in to comment.

More Answers (2)

There are two ways you can do this
1. Make the sliderterminal, sliderinitial, sliderthreshold variables global and use them directly in the callbacks without a need of passing them as arguments.
2. In the callback property of the radio buttons, instead of passing the functions initialcutoff, terminalcutoff, thresholdindex, create anonymous functions that call these functions with the required arguments. For instance,
rinitial = uicontrol(bg,'Style','radiobutton','Callback', @(varargin) initialcutoff(sliderthreshold, sliderinitial, sliderterminal));
You can code similarly for the other buttons as well.

2 Comments

Global variables are a bad idea in every case.
Thanks for your help shantanu!
I agree that global variable would easily solve this problem, but I've read in the matlab documentation that global variables are not good programming practice. Since I am new, I am wary of what I am told to be a problem in the future, I'm going to try to stay away from them.
Thank you again for your input, I very much appreciate you taking the time to respond!

Sign in to comment.

Jan
Jan on 11 Jul 2018
Edited: Jan on 11 Jul 2018
You can use one callback for all 3 radio buttons:
handles.p = uipanel;
handles.slider(1) = uicontrol(p, 'Style', 'slider');
handles.slider(2) = uicontrol(p, 'Style', 'slider');
handles.slider(3) = uicontrol(p, 'Style', 'slider');
handles.bg = uibuttonggroup(p);
uicontrol(bg, 'Style', 'radiobutton', 'Callback', {@initial, handles, 1})
uicontrol(bg, 'Style', 'radiobutton', 'Callback', {@initial, handles, 2})
uicontrol(bg, 'Style', 'radiobutton', 'Callback', {@initial, handles, 3})
function initial(RadioH, EventData, handles, Index)
set(handles.slider, 'Visible', 'off');
set(handles.slider(Index), 'Visible', 'on');
end

1 Comment

Thank you so much for helping me Jan!
This solution works perfectly!

Sign in to comment.

Categories

Find more on Interactive Control and Callbacks in Help Center and File Exchange

Asked:

on 10 Jul 2018

Commented:

on 13 Jul 2018

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!