Properly using button/checkbox callback

1.3k views Asked by At

I have some problems when it comes to defining a callback function and using handles.

 h1 = uicontrol('style','pushbutton','units','pixels',...
                 'position',[40,5,70,20],'string','test',...
                'callback',@h1_call);

I create a button with the code above and want to plot some information stored in the handles if I push on this button.

function h1_call(handles)
axes(handles.ax1)
plot(handles.x,handles.y);

sadly this doesn't work and I dont know why. (also tried to predefine the input with {@p_call,handles} but this didn't help either)

Thank you for your help!

EDIT1: I receive the following error:

Error using GUIname>h1_call
Too many input arguments.

Error while evaluating UIControl Callback

EDIT2: For most cases the mentioned solution works fine. But if I create a checkbox and in the checkbox callback want to see if its value is 1 or 0 I still get an error:

handles.CB_1 = uicontrol('style','checkbox','units','pixels',...
                'position',[40,12,200,30],'string','try1','fontsize',16,...
                'callback',{@CB_1_Callback,handles});
guidata(hObject,handles);

_

function CB_1_Callback(a1,a2,handles)   
if get(handles.CB_1,'Value')==1
disp('Value=1');
elseif get(handles.CB_1,'Value')==0
disp('Value=0');
end

Error:

Reference to non-existent field 'CB_1'.

Error in GUIname>CB_1_Callback (line 569)
if get(handles.CB_1,'Value')==1

Error while evaluating UIControl Callback
1

There are 1 answers

7
Benoit_11 On BEST ANSWER

You have a couple alternatives here. Be aware that callbacks expect 2 input arguments by default so your problem most likely comes from that. I can't find the reference I once saw about this, but you might want to try one of these:

1) In your callback, manually retrieve the data stored in the handles structure.

When creating the pushbutton, add the 2 input arguments even if you don't use them:

h1 = uicontrol('style','pushbutton','units','pixels',...
                 'position',[40,5,70,20],'string','test',...
                'callback',@(s,e) h1_call);

Now somewhere after creating the uicontrols, you want to update the guidata of your GUI, that is, using this command:

guidata("handles to figure", handles)

here "handles to figure" is the handles to the current figure. Each time you modify something in the handles structure, you want to update the data associated with the figure. Here again I'll let you read about this.

Then let your callback function look like this:

function h1_call(handles)
handles = guidata("handles to figure")
axes(handles.ax1)
plot(handles.x,handles.y);

2) Add handles as an argument to the callback when creating the pushbutton,enclosed in {} as you mentioned you already tried, but this time provide 3 input arguments in the callback.

So the pushbutton code looks like this:

h1 = uicontrol('style','pushbutton','units','pixels',...
                     'position',[40,5,70,20],'string','test',...
                    'callback',{@h1_call,handles});

and the callback:

function h1_call(DumyA,DummyB,handles)

    axes(handles.ax1)
    plot(handles.x,handles.y);

The first 2 arguments are not used and have special functions, I'll let you look into them in the docs.

EDIT

As for your question (Edit 2), in this case you only need to provide the 2 default arguments to the callback (which you don't use, so you can replace them with ~). Well actually you could use the 1st argument but that's another story. To be honest I don't know why in this specific case you have to do that...

Anyhow using the following works fine:

function testfig
clear
clc

hFig = figure;
handles.CB1 = uicontrol('style','checkbox','units','pixels',...
    'position',[40,12,200,30],'string','try1','fontsize',16,...
    'callback',{@CB_1_Callback});

guidata(hFig,handles);

%// Don't consider the arguments. 
    function CB_1_Callback(~,~)

        if get(handles.CB1,'Value')==1
            disp('Value=1');
        elseif get(handles.CB1,'Value')==0
            disp('Value=0');
        end
    end

end

Hope that helps!