getappdata works to load a variable that was never set?

Hi I've been using getappdata/setappdata to share variables across different callbacks in my GUI.
Basically what happens is that the user calls a one of the callbacks to load an image into the application and i used setappdata, so that the image can be called somewhere else.
the problem i discovered while debugging on the line of code : >> mask=getappdata(0,'mask');%recieve the mask
if i read this line even without having saved the variable "mask" (with setappdata) somehow the variable mask still gets loaded into the workspace.
does anyone know what causes this? how i can correct it? or if there is an alternative to sharing variables across callback

3 Comments

Your title "getappdata works to load a variable that was never set?" is incorrect: the variable was set, the first time you ran that code. This is the problem here:
getappdata(0,...)
You are storing in the root graphics object (0), which is just as bad as using global variables: it produces untraceable bugs that are almost impossible to debug. Just like you are finding out now.
is there some way i can use getappdata without storing it in a root object? if not what is a good alternative?
"is there some way i can use getappdata without storing it in a root object?"
Read the setappdata / getappdata help, which list all of the different graphics object types that you can use.

Sign in to comment.

 Accepted Answer

Jan
Jan on 30 Sep 2017
Edited: Jan on 30 Sep 2017
It is a bad style to share data using the root object 0. This has the same problems as using global variables and you find thousands of explanations in this forum and the net about the severe problems caused by globals.
Better share variables of callbacks by storing them in the figure. Then you can e.g. run multiple instances of a GUI without interferences.
Your description is not clear. As far as I understand you run
data = getappdata(0, 'AVariableNotCreatedBefore')
and are surprised that [] is returned. This is exactly, what is defined in the documentation:
help getappdata
... If the application-defined data does
not exist, an empty matrix will be returned in VALUE.
Perhaps you want to check the existence at first:
if isappdata(0, 'AVariableNotCreatedBefore')
data = getappdata(0, 'AVariableNotCreatedBefore');
else
error('Request not existing variable');
end
Or perhaps you have the problem, that the globally set variable is not cleared, when the GUI is closed. This is expected also, because you stored it in the root object. Then the solution is mentioned already: Store the data in the figure and not globally.

7 Comments

>>Your description is not clear. As far as I understand you run
>>data = getappdata(0, 'AVariableNotCreatedBefore') >>and are surprised that [] is returned
the problem is that it doesnt return []. it returns an image that was defined the last time i ran the GUI, but now my workspace is empty and when i run the line (in isolation using F9)
data = getappdata(0, 'AVariableNotCreatedBefore')
it returns the variable that was defined the last time i used the gui. though as far as i can tell it should return an [] because it should know that the variable exists.
I hope this clarifies. It sounds to me like this is what you were describing:
>>Or perhaps you have the problem, that the globally set variable is >>not cleared, when the GUI is closed. This is expected also, because >>you stored it in the root object. Then the solution is mentioned >>already: Store the data in the figure and not globally.
if so perhaps there is a way i can store it not in a root object? if not can you please direct me to an article that discusses storing the data in a figure.
Hope that helped to clarify the question. Thank You
"..but now my workspace is empty.."
What is in your workspace is irrelevant, as the appdata is not stored in any workspace. Jan Simon explained that it is not a surprise that once you have defined 'mask' in the graphics root object then it still exists next time you try to access it: the graphics root object always exists, so whatever you store in it is also going to hang around until you exit MATLAB. The solution is to NOT put 'mask' in the graphics root.
"perhaps there is a way i can store it not in a root object? if not can you please direct me to an article that discusses storing the data in a figure."
Probably the most popular location is the GUI figure. When you read the setappdata help (which I reccomend that you should), it clearly states the the first input " obj — Graphics object in which to store the value. figure | uipanel | uibuttongroup | uicontrol | ..."
Simply use an appropriate graphics object instead of zero (zero being the graphics root, and not the place where you should be storing GUI data!). See the explanation and examples here:
You might also want to read about the graphics object hierarchy:
I am attempting to save the data to a figure as per your advice.
fig_in=figure;set(fig_in, 'Visible', 'off');
setappdata(fig_in,'in',in);%save so that we may use them in a different callback functions
this is in the callback where the variable "in" is defined and then in another callback
getappdata(fig_in,'in');
however im getting an error: undefined function or variable 'fig_in' can you please clarify the correct way to do this?
Use the Parent property. I have given the link to the setappdata help, which has examples of how to do this. As I wrote earlier, you need to read the MATLAB documentation.
@Betzalel: Do you know the so called wrapper function guidata? It calls get/setappdata also internally using the figure handle. This is frequently used to store data locally in the figure:
function YourCallback(hObject, EventData, handles)
handles.Mask = (rand(3) < 0.5); % For example
guidata(hObject, handles); % Store modified handles struct in the figure
end
function AnotherCallback(hObject, EventData, handles)
Mask = handles.Mask;
...
end
guidata determines the parent figure belonging to the object hObject automatically. But you can do this with set/getappdata directly also:
function YourCallback(hObject, EventData, handles)
FigH = ancestor(hObject, 'figure'); % [EDITED, Typo fixed]
Mask = (rand(3) < 0.5); % For example
setappdata(FigH, 'Mask', Mask);
end
function AnotherCallback(hObject, EventData, handles)
FigH = ancestor(hObject, 'figure');
Mask = getappdata(FigH, 'Mask');
...
end
Note that the handles of the figure is contained in the handles struct also. You can check this by using the debugger.
I found the guidata function while i was waiting to hear back from you.
I believe the 2nd solution (the one with the figures) will be better since i can do it via an external function.
Thank you very much for your assistance!

Sign in to comment.

More Answers (0)

Categories

Find more on Interactive Control and Callbacks in Help Center and File Exchange

Asked:

on 30 Sep 2017

Edited:

Jan
on 1 Oct 2017

Community Treasure Hunt

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

Start Hunting!