6

I am working on GUI. I want to store data in extra fields created in handles structure. However, I don't know how to update handles structure properly when callback function ends. Please, give any advice.

My simplified program

  • Set number of signal (1-10). Each signal has 3 parameters.
  • Read parameter for selected signal from array created in handles structure (default are zeros).
  • Edit parameter, update the array.

GUI

function simple_gui(hObject, h)

h.fig = figure(...
    'Units','pix',...
    'Position',[50 50 500 400],...
    'Visible','default',...
    'Name','GUI',...
    'NumberTitle','off',...
    'Resize','on');

table = {'1' , '2', '3' , '4', '5', '6', '7', '8', '9', '10' };

h.number = uicontrol(...
    'Units','characters',...
    'Max',10,...
    'Min',1,...
    'String',table,...
    'Style','popupmenu',...
    'Value',1,...
    'Position',[37.4 28.3846153846154 19.4 1.61538461538462],...
    'BackgroundColor',[1 1 1]);

h.edit1 = uicontrol(...
    'Units','pix',...
    'String','0',...
    'Style','edit',...
    'Position',[180 280 50 20],...
    'BackgroundColor',[1 1 1],...
    'FontSize',10);

h.edit2 = uicontrol(...
    'Units','pix',...
    'String','0',...
    'Style','edit',...
    'Position',[180 255 50 20],...
    'Children',[],...
    'FontSize',10);

h.edit3 = uicontrol(...
    'Units','pix',...
    'String','0',...
    'Style','edit',...
    'Position',[180 230 50 20],...
    'FontSize',10);

Main code:

h.parameter1 = zeros(1,10);
h.parameter2 = zeros(1,10);
h.parameter3 = zeros(1,10);
h.signal_no = 0;

h.number.Callback = {@number_Callback, h};

h.edit1.Callback = {@parameter_change_Callback, h};
h.edit2.Callback = {@parameter_change_Callback, h};
h.edit3.Callback = {@parameter_change_Callback, h};
guidata(h.fig, h);

function number_Callback(hObject,eventdata, h)
h = guidata(hObject);
h.signal_no = hObject.Value;
k = h.signal_no;
h.edit1.String = h.parameter1(k);
h.edit2.String = h.parameter2(k);
h.edit3.String = h.parameter3(k);
guidata(hObject,h);

function parameter_change_Callback(hObject,eventdata, h)
h = guidata(hObject);
k = h.signal_no;
h.parameter1(k) = str2double(h.edit1.String);
h.parameter2(k) = str2double(h.edit2.String);
h.parameter3(k) = str2double(h.edit3.String);
guidata(hObject, h);
K.Ramel
  • 61
  • 2
  • You need to add `guidata(hObject,h);` at the end of your function. You also need to add two inputs to your function `function simple_gui(hObject,h)` – Anthony May 01 '17 at 15:08
  • @Anthony, I added commands you mentioned, but it didn't helped. I get an error "Reference to non-existent field 'parameter1'". However, when I wrote similar program using GUIDE it works fine. But I prefer to write code programmaticaly and I want to learn how to get it working. – K.Ramel May 01 '17 at 15:51
  • Sorry, my suggestion was terribly wrong. I misunderstood your code. I will check your code later, if it is still not answered – Anthony May 01 '17 at 16:31
  • You have to store your initialized parameters with `guidata` too. – sco1 May 01 '17 at 16:35
  • @excaza, that alone didn't solve the problem. I'm reading some documentation [here](http://148.204.81.206/matlab/creating_guis/sharing-data-among-a-guis-callbacks.html). The author uses global variables, which is an option, but not a good one. – Anthony May 01 '17 at 16:49
  • 2
    @Anthony it would solve the problem if he did it. He initializes his data in the handles structure but never stores it, hence why the callbacks error when attempting to access the field in the structure. It doesn't exist, the error message is pretty clear. – sco1 May 01 '17 at 17:07
  • 1
    @excaza well yes, screw me, you were right. just add `guidata(h.fig, h);` before `function number_Callback(hObject,eventdata, h)` – Anthony May 01 '17 at 17:15
  • 1
    Thank you for replies. I updated my code and it works now. If I encounter another problems I will call you here or post another question. – K.Ramel May 01 '17 at 18:08

1 Answers1

1

In summary:

Call guidata(handleObject, varToStore) (documentation) at the end of GUI callback functions to ensure updates to one modified variable are stored. Here, handleObject is either your figure's handle or a child of it, and varToStore is the updated variable you want stored; it is often a structure.

The syntax for retrieving stored data from a figure or child handle:

handles = guidata(gcbo);  % gcbo will get the callback object (instance of handle class).  
handles.propToUpdate = handles.propToUpdate+1;  
guidata(gcbo,handles);    % stores the updated struct 

In addition:

You won't see the changes from your popupmenu reflected in your edit boxes in the GUI with the current code because you are assigning the numeric values to a edit handle's String field. You call str2double() when taking values this field, and just need to do the reverse (num2str()) to get the displayable values back in. Here's the updated code with a simplified callback declaration

h.number.Callback = @number_Callback;

function number_Callback(hObject,~)
    h = guidata(hObject);
    h.signal_no = hObject.Value;
    k = h.signal_no;
    h.edit1.String = num2str(h.parameter1(k));
    h.edit2.String = num2str(h.parameter2(k));
    h.edit3.String = num2str(h.parameter3(k));
    guidata(hObject,h);
 end
informaton
  • 1,462
  • 2
  • 11
  • 20