1

I'm making a GUI that reads out data from a measurement board via a serial interface. It consists of 8 channels and I want to be able to enable and disable the channels in the figure plot, but the state of my variable handles.channelsEnable isn't saved.

When opening the GUI: handles.channelEnable = [0;0;1;1;0;0;0;0]; While running the GUI I want to modify a handles.channelEnable. Inside the callback function of a checkbox it is changed, but not outside the function. I'm using guidata(hObject,handles) to save the changes made. Why aren't the changes made to handles.channelEnable saved?

    % --- Executes on button press in checkbox2.
    function checkbox2_Callback(hObject, eventdata, handles)
    % hObject    handle to checkbox2 (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)

    % Hint: get(hObject,'Value') returns toggle state of checkbox2
        handles.channelEnable(2) = get(hObject,'Value');
        guidata(hObject, handles);
    end
cor55555
  • 13
  • 2

3 Answers3

1

@YisasL's answer is the correct one, but I wanted to clarify it a bit.

When providing an input variable to a callback function, the variable that is passed when you invoke the callback is that variable as it exists when the callback is defined. You can see this with a simple example:

function testcode
handles.mainwindow = figure();

handles.button1 = uicontrol( ...
    'Style','pushbutton', ...
    'Units','normalized', ...
    'Position',[0.05 0.05 .30 .90], ...
    'String','Button1', ...
    'Callback',{@button1,handles} ...
    );
handles.button2 = uicontrol( ...
    'Style','pushbutton', ...
    'Units','normalized', ...
    'Position',[0.35 0.05 .30 .90], ...
    'String','Button2', ...
    'Callback',{@button2,handles} ...
    );
handles.button3 = uicontrol( ...
    'Style','pushbutton', ...
    'Units','normalized', ...
    'Position',[0.65 0.05 .30 .90], ...
    'String','Button3', ...
    'Callback',{@button3,handles} ...
    );
end

function button1(~,~,handles)
fieldnames(handles)
end

function button2(~,~,handles)
fieldnames(handles)
end

function button3(~,~,handles)
fieldnames(handles)
end

Push each button and look at the displayed output from fieldnames. You'll notice that button 1 only has mainwindow, button 2 has mainwindow and button1, and button3 has mainwindow, button1, and button2. As you've now noticed, no matter what changes you make elsewhere in your code, this result will remain constant.

It's an interesting quirk I noticed when I moved to programmatic GUIs rather than utilizing GUIDE. You generally don't notice with a GUIDE GUI because all of the initialization is taken care of in the background and the users don't tend to modify the handles structure. With a programmatic GUI you need to be conscious of the order in which you define your callbacks (define them after your handles structure is built).

The alternative is to utilize guidata like @YisasL said. Then you don't need to worry about passing variables to your callbacks.

sco1
  • 12,154
  • 5
  • 26
  • 48
0

You can use guidata to include a new handle in the handles variable, but whenever you want to use handles you must call guidata to obtain them. The variable handles as input variable of the callback won't have it included.

YisasL
  • 315
  • 1
  • 11
  • I don't think I fully understand you. Do you mean that I have to add guidata(hObject) to get the handles? So the code looks like this: % --- Executes on button press in checkbox2. function checkbox2_Callback(hObject, eventdata, handles) handles guidata(hObject); handles handles.channelEnable(2) = get(hObject,'Value'); guidata(hObject,handles); end It does not make any difference with or without. In both cases all handles are known (also channelEnable)l – cor55555 Jul 31 '14 at 12:04
  • I mean that when you callback is called, you will receive `handles` as input variable, but it will not contain the full list of handles. If you want to have all of them (which you also included before with `guihandles(hObject, handles)`), you have to call `guihandles` again inside the callback to get ALL. Is it clear now? :) – YisasL Jul 31 '14 at 12:16
  • I still don't get it. It makes no difference, I think I'm still doing something wrong. Could you write down the code I have to put in the checkbox callback (literally)? When I look in the MATLAB documentation it says "If you use GUIDE, you do not need to call guihandles to create a structure, because GUIDE generates a handles structure that contains the GUI's handles. You can add your own data to it". See [link](http://www.mathworks.nl/help/matlab/ref/guidata.html?searchHighlight=guidata) – cor55555 Jul 31 '14 at 13:21
  • But you have included a new control in `handles` manually. To have the whole list of handles just put 'handles = guihandles;' after 'function checkbox2_Callback(hObject, eventdata, handles)' (that is to say, the first line after the checkbox callback is called). If you still have problems, see @excaza 's answer also. – YisasL Jul 31 '14 at 13:30
  • 1
    It works! Thanks a lot! Now I understand. At beginning of EVERY function or callback (not only the callback of the checkbox) you have to load the handles structure with 'handles = guidata(hObject);' and at the end of EVERY function or callback you have to save the handles structure with 'guidata(hObject,handles);'. My fault was that I didn't load the handles structure again in the function where I used channelEnable. – cor55555 Jul 31 '14 at 17:28
0

I don't think I fully understand you.

Do you mean that I have to add guidata(hObject) to get the handles? So the code looks like this:

% --- Executes on button press in checkbox2.
function checkbox2_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of checkbox2
    handles
    guidata(hObject);
    handles
    handles.channelEnable(2) = get(hObject,'Value');
    guidata(hObject, handles);
end

It does not make any difference with or without. In both cases all handles are known (also channelEnable).

cor55555
  • 13
  • 2