MATLAB: How to update guidata in the addlistener callback function

addlistenerguiguidataMATLAB

I am developing a program for a company.
In the GUI I first grouped a number of checkboxes into one handle object (for instance I have 10 checkboxes).
for i = 1 : 10
checkboxes(i-1) = handles.(sprintf('checkbox%d', i));
end
handles.checkboxes= checkboxes;
Then I used the addlistener function to detect any changes for the group of checkboxes.
addlistener(handles.checkboxes, 'Value', 'PostSet', @(hObject, eventdata, handles) callback(hObject, eventdata, handles));
In the callback function, I wanted to update the value for 'anyObject' and in the end of the function I updated the handles structure so that the value of the 'anyObject' can be used by other functions.
function handles = callback(hObject, eventdata, handles)
handles.anyObject = get(handles.checkbox1,'Value');
% Update handles structure
guidata(hObject, handles);
The problem I have is that the program always throws me this error whenever I click the checkbox button:
Warning: Error executing listener callback for PostSet event on Value dynamic property in object of
matlab.ui.control.UIControl class:
Not enough input arguments.

Best Answer

Note:
for i = 1:10
checkbox(i-1) = ...
will error on the first iteration, since checkbox(1-1=0) is not a valid index.
Note 2:
@(hObject, eventdata, handles) callback(hObject, eventdata, handles)
Since this anonymous function only job is to pass all its inputs to another function unchanged, it could just be skipped. That is
@callback
would do the same.
Note 3:
function handle = callback(...)
A proper callback never returns anything since there is no mechanism for getting that return value.
Now for your question, the immediate problem comes from the anonymous function you've defined. An listener callback must have two inputs arguments and only two. These are, the object generating the event, and some event data. Therefore, the inputs to your anonymous function can only be:
@(hobject, eventdata) ...
handles cannot be an input since it won't be sent by the event. Now, if you wanted handles to be passed to your callback function, you could define your anonymous function as:
@(hobject, eventdata) callback(hobject, eventdata, handle)
This would work with you example, but I wouldn't recommend that. The anonymous function captures the content of the handle structure at the point it is defined, so any change to that handle structure after that line won't be seen by your callback, e.g.:
lh = addlistener(handles.checkboxes, 'Value', 'PostSet', @(hObject, eventdata) callback(hObject, eventdata, handles));
handles.text = uicontrol('Style', 'text', 'String', 'some new control'); %add a new control to handle
The handle received by your callback will not contain the text field as it was created after handle was captured.
A safer way is simply to get the handle structure with guidata inside your callback, so:
lh = addlistener(handles.checkboxes, 'Value', 'PostSet', @callback); %not passing handle to callback
function callback(hObject, eventdata) %not receiving handle
handle = guidata(hobject); %get handle inside the callback.
%...