UI Control callback function problem

I have done a small program based on show in a static text the values of the slider everytime I touch the slider. I'm working in dot notation ( e.g. no using get and set )and without using GUIDE. I don't know how to use the callback function for make it works, even I know the command that works.
Here is the program:
%%Figure Creation
fig = figure
fig.Color = 'b'
fig.Tag= 'fig1'
fig.Name= 'SliderGUI'
%%Slider Creation
slider = uicontrol('Parent',fig,'Style','Slider','Min',0,'Max',1, ...
'SliderStep',[0.01 0.10], 'Position', [100,100,300,25]);
slider.BackgroundColor = 'k'
slider.Tag = 'slider1'
slider.Callback=@sliderCallback
%%Create of UIControl Static text
static = uicontrol ('Parent',fig,'Style','text','Position', ...
[100,150,300,250], 'Value', 0 ,'String', 'Slider Value');
static.FontName = 'Arial';
static.FontSize =100;
static.BackgroundColor = 'c'
static.Tag = 'static1'
static.Callback=@staticCallback
%%Slider Callback function
% Here is where I have problems
function sliderCallback(slider,eventdata)
static.String=slider.Value
end
The command
static.String=slider.Value
Works good, but I don't know how to define the callback function. I try a lot of things but anything have worked.
Thank's for the help!

 採用された回答

Walter Roberson
Walter Roberson 2016 年 11 月 12 日

0 投票

Change
function sliderCallback(slider,eventdata)
static.String=slider.Value
end
to
function sliderCallback(slider,eventdata)
static = findobj(ancestor(slider, 'figure'), 'Tag', 'static1');
static.String = slider.Value
end
That is, your problem is that "static" is not in scope in the sliderCallback so you have to locate it.

5 件のコメント

Walter Roberson
Walter Roberson 2016 年 11 月 14 日
You need R2016b or later in order to be allowed to have a function definition inside a .m file that does not start with either function or classdef
You can do one of the following:
  • move the function to its own sliderCallback.m file; or
  • upgrade to R2016b; or
  • put function followed by your .m file name at the beginning of your code, before that '%% Figure Creation'; or
  • remove the function entirely and change
static.Callback=@staticCallback
to
static.Callback = @(src, event) set(static, 'String', get(slider, 'Value') );
Pau Papu
Pau Papu 2016 年 11 月 18 日
Thank's Walter,
I have realized also that my problem is that the callback function is a nested function and for work well it needs to have a general function. Then, even if I just do:
static.String=slider.Value
The slider callback works well. But I understand that I have always to put my variable in scope
I have a question concerning this topic: Can I add the handles of the different objects I will need just adding arguments into the callback cell array? I mean:
slider.Callback={@sliderCallback,static}
Is that another way to have the variables in scope?
The function works well doing that but I want to verify if I'm understanding well the concept.
Thank you very much!
Thank you
Walter Roberson
Walter Roberson 2016 年 11 月 18 日
You have to be a bit careful with something like
slider.Callback={@sliderCallback,static}
It is a quite important technique, but you need to remember that when you do that, what will be passed to each callback invocation will not be the whatever the variable static has been assigned at the time of the invocation. Instead, what will be passed to the callback invocation is a copy of whatever static was at the time that the cell array was constructed. If static is changed after that, then the callback will not get the updated version.
If static is a handle (as it is in your code) then provided the handle is not destroyed, then that works out fine because the handle does not itself hold the properties and instead just says where the properties are to be found, and the location to be found at does not change even when the properties change.
But if static is instead something like a structure, such as the handles structure, then any new fields added to the structure after the callback is created will not exist in the invocation of the callback, and any non-handle fields would retain their old values. For example,
handles = guidata(hObject);
handles.filename = '';
handles.folder = '';
handles.slider = uicontrol(....);
handles.slider.Callback = {@sliderCallback, handles};
[handles.filename, handles.folder] = uigetfile('*.jpg', 'Select an image');
guidata(hObject, handles);
then the version of handles received by callback invocations would not have the updated filename and folder fields.
Pau Papu
Pau Papu 2016 年 11 月 24 日
編集済み: Walter Roberson 2016 年 11 月 24 日
Thanks for the answer Mr.Robertson,
I understand your explanation but I tried to run this last small code but doesn't work. I will appreciate to understand more the context. For what I have read, I should do that:
fig1=figure
handles=guihandles(fig1)
And then, fill the fields:
handles.filename=''; etc
And finally store this data using guidata:
guidata(fig1,handles)
I'm understanding that well? I have some doubts concerning what is a handle...
I have some other questions:
1-You say that in my code, static is a handle because everytime I create a uicontrol ( or a figure ) it's by definition a handle object from the handle class?
2- In your code, you first create a structure of handles but you can add fields that are not handles ( as character vectors, and other structures...) using guihandles/guidata. It's better to proceed like that? Because I am not habituated to use guihandles/guidata.
3-There is any reference for understand all that?
Thank you very much!
Walter Roberson
Walter Roberson 2016 年 11 月 24 日
graphics routines were defined as returning handles long before object oriented classes existed in MATLAB.
People tend to over-use adding non-handle fields to the handles structure. It is a useful structure, but it can lead to performance problems. GUIDE uses the handles structure for every graphics callback, so for every GUIDE graphics callback, the entire contents of the handles structure is copied. If a lot of non-handle data has been stored in handles then that can take a lot of time and memory. Most callbacks only need access to a modest number of entries from the handles structure. My suggestion is that you never save large arrays to the handles structure: instead store them using setappdata(), as then you can request just that data with getappdata() when you need it, without it being copied when it is not needed.

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

ヘルプ センター および File ExchangeInteractive Control and Callbacks についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by