MATLAB Answers

guidata(hObject, handles) does not save my data

1 view (last 30 days)
Lukas Nolle
Lukas Nolle on 11 Jul 2021
Commented: Lukas Nolle on 11 Jul 2021
Hi,
In the following function i try to calculate the number of vectors in a rectangle. (result stored in handles.num)
In Debug-mode the number gets calculated correctly, but when it jumps out of the function, the generated data gets deleted form the workspace and the next function, that tries to access that data throws an error message.
I tried to update handles, but apparently it doesn`t work the way i think it would.
The function, that claclutates the number:
function calcHatch(hObject, eventdata, handles)
handles.num=0;
invert = false;
handles.N_hatches = floor((handles.size_y-handles.hatchO)/handles.hatchD); %abgerundete Anzahl der Hatchlinien
handles.hatches = (1:1:handles.N_hatches); %erste Zeile des Arrays mit den Nummern der Hatchreihen befüllen
for h = 1:(handles.N_hatches)
handles.hatches(2, h) = handles.hatchO + handles.hatchD*(h-1); %zweite Zeile des Arrays mit den Offsets der Hatchreihen befüllen
handles.hatches(3, h) = 1;
if (handles.hatches(2, h) >= handles.o_Pocket_1 & handles.hatches(2, h)<=(handles.o_Pocket_1+handles.s_Pocket_1)) %dritte Zeile mit Anzahl der Hatches der Hatchlinien füllen
handles.hatches(3, h) = handles.hatches(3, h) + 1;
end
if (handles.hatches(2, h) >= handles.o_Pocket_2 & handles.hatches(2, h)<=(handles.o_Pocket_2+handles.s_Pocket_2))
handles.hatches(3, h) = handles.hatches(3, h) + 1;
end
if (handles.hatches(2, h) >= handles.o_Pocket_3 & handles.hatches(2, h)<=(handles.o_Pocket_3+handles.s_Pocket_3))
handles.hatches(3, h) = handles.hatches(3, h) + 1;
end
if (handles.hatches(2, h) >= handles.o_Pocket_4 & handles.hatches(2, h)<=(handles.o_Pocket_4+handles.s_Pocket_4))
handles.hatches(3, h) = handles.hatches(3, h) + 1;
end
handles.num=handles.num + handles.hatches(3, h);
handles.hatches (4, h) = invert; %vierte Zeile mit der Information, ob Hatchlinie invertiert werden muss, befüllen
invert = not(invert);
end
guidata(hObject,handles);
The function, that tries to accesss the data:
function importFile(hObject, eventdata, handles)
[handles.filename, handles.pathname] = uigetfile('*', 'Select the txt-file'); %öffnen des Dateiverzeichnisses um Datei auszuwählen
FID = fopen(fullfile(handles.pathname,handles.filename),'r+'); %öffnen der ausgewählten Datei
h=textscan(FID,'%s',14); %Abspeichern des Headers
handles.header=h{1}(:);
C = textscan(FID, '%s',(handles.num)*4+3,'delimiter',','); %auslesen der Datei
handles.dat=C{1}(:);
s=textscan(FID,'%s'); %Abspeichern der Informationen nach den manipulierten Daten
handles.signature=s{1}(:);
guidata(hObject, handles);
fclose(FID);
The error-message:
Unrecognized field name "num".
Error in Hatchmanipulation>importFile (line 185)
C = textscan(FID, '%s',(handles.num)*4+3,'delimiter',','); %auslesen der Datei
Error in Hatchmanipulation>pushbutton1_Callback (line 268)
importFile(hObject, eventdata, handles);
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in Hatchmanipulation (line 42)
gui_mainfcn(gui_State, varargin{:});
Error in
matlab.graphics.internal.figfile.FigFile/read>@(hObject,eventdata)Hatchmanipulation('pushbutton1_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback.
Maybe someone has an idea what i am doing wrong.
Thanks in advance.

Accepted Answer

Jan
Jan on 11 Jul 2021
How did you create the GUI? This does not look as GUIDE. How are the callbacks called? Directly as defined during the creation of the GUI objects? Then remember, that the handles struct is a copy of the struct as it existed during the creaion of the GUI:
function createGUI
handles.FigH = figure;
handles.data = [0, 0];
handles.Button1 = uicontrol('Style', 'pushbutton', ...
'String', 'button 1', ...
'Units', 'normalized', ...
'Position', [0.1, 0.1, 0.35, 0.1], ...
'Callback', {@Button1CB, handles});
handles.Button2 = uicontrol('Style', 'pushbutton', ...
'String', 'button 2', ...
'Units', 'normalized', ...
'Position', [0.55, 0.1, 0.25, 0.1], ...
'Callback', {@Button1CB, handles});
guidata(handles.FigH, handles);
end
function Button1CB(Button1, Event, handles) % Get struct from function def
handles.data(1) = handles.data(1) + 1;
disp(handles.data);
guidata(Button1, handles); % Modifies struct stored in figure
end
function Button2CB(Button1, Event, handles) % Get struct from function def
handles.data(1) = handles.data(1) + 1;
disp(handles.data);
guidata(Button1, handles); % Modifies struct stored in figure
end
Now there are 3 different copies of the handles struct. One with data=0 is stored in the inputs of Button1CB, one with data=1 in the inputs of Button2CB and the a 3rd one in the figure.
GUIDE solves this by replacing the 3rd input by a copy of the current hanbdles struct from the figure. This can be done manually also:
function createGUI
handles.FigH = figure;
handles.Button1 = uicontrol('Style', 'pushbutton', ...
'String', 'button 1', ...
'Units', 'normalized', ...
'Position', [0.1, 0.1, 0.35, 0.1], ...
'Callback', @Button1CB); % Without providing handles
handles.Button2 = uicontrol('Style', 'pushbutton', ...
'String', 'button 2', ...
'Units', 'normalized', ...
'Position', [0.55, 0.1, 0.25, 0.1], ...
'Callback', @Button1CB); % Without providing handles
handles.data = [0, 0];
guidata(handles.FigH, handles);
end
function Button1CB(Button1, Event)
handles = guidata(Button1);
handles.data(1) = handles.data(1) + 1;
disp(handles.data);
guidata(Button1, handles);
end
function Button2CB(Button1, Event)
handles = guidata(Button1);
handles.data(2) = handles.data(2) + 1;
disp(handles.data);
guidata(Button1, handles);
end
With this way, you have one copy of the handles struct only and it is stored in the figure.
  1 Comment
Lukas Nolle
Lukas Nolle on 11 Jul 2021
I used GUIDE to create the GUI. I didn't change the way the automatically generated callbacks are called. The user can input data via uitables, so i have changed the callbacks to store the data upon CellEdit.
I changed the function according to your second example and it worked.
The functions now is:
function calcHatch(hObject, eventdata)
handles=guidata(hObject);
handles.num=0;
invert = false;
handles.N_hatches = floor((handles.size_y-handles.hatchO)/handles.hatchD); %abgerundete Anzahl der Hatchlinien
handles.hatches = (1:1:handles.N_hatches); %erste Zeile des Arrays mit den Nummern der Hatchreihen befüllen
for h = 1:(handles.N_hatches)
handles.hatches(2, h) = handles.hatchO + handles.hatchD*(h-1); %zweite Zeile des Arrays mit den Offsets der Hatchreihen befüllen
handles.hatches(3, h) = 1;
if (handles.hatches(2, h) >= handles.o_Pocket_1 & handles.hatches(2, h)<=(handles.o_Pocket_1+handles.s_Pocket_1)) %dritte Zeile mit Anzahl der Hatches der Hatchlinien füllen
handles.hatches(3, h) = handles.hatches(3, h) + 1;
end
if (handles.hatches(2, h) >= handles.o_Pocket_2 & handles.hatches(2, h)<=(handles.o_Pocket_2+handles.s_Pocket_2))
handles.hatches(3, h) = handles.hatches(3, h) + 1;
end
if (handles.hatches(2, h) >= handles.o_Pocket_3 & handles.hatches(2, h)<=(handles.o_Pocket_3+handles.s_Pocket_3))
handles.hatches(3, h) = handles.hatches(3, h) + 1;
end
if (handles.hatches(2, h) >= handles.o_Pocket_4 & handles.hatches(2, h)<=(handles.o_Pocket_4+handles.s_Pocket_4))
handles.hatches(3, h) = handles.hatches(3, h) + 1;
end
handles.num=handles.num + handles.hatches(3, h);
handles.hatches (4, h) = invert; %vierte Zeile mit der Information, ob Hatchlinie invertiert werden muss, befüllen
invert = not(invert);
end
guidata(hObject,handles);
Thank you very much.

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 11 Jul 2021
You may have created it in GUIDE but if you did you either overrode the default names for the control callbacks, which will have a _Callback at the end of the control name, eg.
function calcHatch_Callback(hObject, eventdata, handles)
but that can't be true unless you also deleted the handles input from the input argument list.
So that leaves us with that you wrote those functions yourself and for some reason give the unneeded input arguments of hObject, eventdata. So if you're writing custom functions in the m-file, you should do this:
function handles = calcHatch(handles)
% code
That way, the callback from your button or other control will pass in the value of handles, then your code can change it, like by adding a num field to it. Then it will return the changed handles structure and the callback function that called your custom function will update handles globally when your callback calls guidata(). So the callback would look like
function button1_Callback(hObject, eventdata, handles)
% Now, here, handles does NOT have a .num field.
handles = calcHatch(handles) % Add a new "num" field to handles structure.
% Now, here, handles has a .num field.
guidata(hObject,handles); % Update handles.
  1 Comment
Lukas Nolle
Lukas Nolle on 11 Jul 2021
You're right, i manually created those functions,
After following the advise of Jan my code is now working, so i will just leave it that way.
Thank you anyway. I will remeber your advise for future projects.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!