How to pass a function workspace into a guidata handles structure in a GUI

Hi guys, I have a function called within a GUI structure callback built with GUIDE that produces a significant number of variables in that function's workspace, and I'd like to use guidata to pass a structure of workspace variables to other callbacks but I can't get the syntax right. In the GUI's opening function I've defined a handles structure called handles.Drive in which I'd like to store the structure:
% --- Executes just before GUIv01b is made visible.
function GUIv01b_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to GUIv01b (see VARARGIN)
% Choose default command line output for GUIv01b
handles.output = hObject;
%Create handles structure to store all data gererated by Drive_Matlab.m
handles.Drive = hObject;
% Update handles structure
guidata(hObject, handles);
Later the callback containing the function is called, and it's the workspace variables produced from a script called Drive_Matlab that I want to pass to handles.Drive:
% --- Executes on button press in GUILoadXLSXFile.
function GUILoadXLSXFile_Callback(hObject, eventdata, handles)
% hObject handle to GUILoadXLSXFile (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
clearvars except (hObject,eventdata,handles);
clear handles.GUIThreatTable.Data;
clear handles.STSProfileDataTable.Data;
clear handles.PlotData, 'Data';
cla reset;
Drive_Matlab; %Assign all workspace variables to handles.Drive
save Drive;
handles.Drive = load(Drive);
guidata(hObject,handles);
The code above represents an attempt to save all workspace variables as Drive.mat and then pull that into the handles structure, but that doesn't seem to work either. A question that just occurred to me: do I need to populate the handles structure handles.Drive from within the function that generates the variables, or is it sufficient to do it from within the GUI callback that contains the call to the function?
Thanks, Jason

8 Comments

The clearvars is useless here, because it is the start of a function.
Having many variables is often a sign of bad programming practice. Generally outside of debugging you shouldn't save your entire workspace, although I see no reason why this code should fail, apart from me having no idea what happens inside that script. If the script executes successfully, the variables it assigns should still be available, and the save/load trick should work.
Hi Rik -
I don't necessarily want to write my workspace variables to a .mat file, what I want to do is pass them to handles.Drive, so I can use guidata to call, say, handles.Drive.var1, handles.Drive.var2 in other GUI component callbacks. At this point, all I need to know is the syntax to send all variables in the workspace of Drive_Matlab into handles.Drive.
@Jason: whatever way you try to access those variables will be slow and complex, whether you use load or something based on whos, they will also be slow. Having so many variables forces you into writing slow, complex, buggy code to access them all: once you made that design decision there is nothing you can do about that. Designing the code better so that it returns one structure in the first place would mean that you could avoid this situation entirely. After all, the best solution is to fix the problem at the source (i.e. so that "...produces a significant number of variables in that function's workspace" does not happen), rather than writing slow, complex hack code to try and work with all of those variables.
You really would be much better off putting all of the data into one array right from when they are created: it might be an ND numeric, a cell, a structure array, a table, etc., depending on the data. All of these classes make it easy to pass the data (just one variable), efficient to access (indexing, fieldnames, variable names), and easy to work with (vectorized code, etc). Your current approach forces you to use slow and complex methods to access your data. Read this to know more:
I can only agree with Stephen on this one, hence my suggestion in the answer: change the script to a function. If you save the variables to fields in handles and save that with guidata, any callback from that same figure will have access to that data when it loads guidata (which happens automatically for your GUI, since GUIDE puts that in the callback).
Thanks guys, I've got a handle on it (pun definitely intended). Jason
Rik and Stephen -
Thanks for your attention to my issue, but I have some feedback on your feedback. I understand that preaching the gospel of good coding practices is important, but in the context of a single coding question, a response along the lines of "write better code and you won't have this problem" is spectacularly UNhelpful. I was working with legacy code handed to me to modify for a specific purpose, and re-engineering the existing code was not an option given my circumstances. A couple of lines of code illustrating the proper syntax for what I was trying to do would have been far more helpful and saved a couple more hours of trial and error. It's not as though handing me some code to address my specific question would have been akin to handing a suicidal person a straight razor. Just saying.
That being said, thank you for your attention in addressing user questions. I'm sure you see predicaments far worse than mine on a daily basis.
'a response along the lines of "write better code and you won't have this problem" is spectacularly UNhelpful'
Thank you for your feedback. Users of this forum are often pleased to learn about simpler and more efficient ways to write their code, and they appreciate the advantages to their own lives (simpler debugging, faster code, etc). I understand that badly-written legacy code is sometimes a "fact of life" beyond our control, but nowhere in your question is this situation explained: it might surprise you to know that we do not posses the magic ability to know the entire background to your task, nor can we see your monitor and all of the code that you are running. We made recommendations based on what you told us, which to my mind was appropriate.
"A couple of lines of code illustrating the proper syntax for what I was trying to do would have been far more helpful and saved a couple more hours of trial and error."
My "spectacularly UNhelpful" comment (which was not provided as an answer to your question) contained a link to a page that lists the main ways to solve your problem. Did you read it?
"It's not as though handing me some code to address my specific question would have been akin to handing a suicidal person a straight razor"
You are right: it would be akin to handing them a chainsaw:
It occurs to me that my tone may have been misinterpreted as being offended, when I certainly didn't mean to come off that way. My apologies for any raised hackles. I did read the article you linked. What I ended up doing to pass the handles I wanted was the following:
Drive_Matlab; %Produces Drive.mat, saves to base workspace
%
save Drive; %Writes original data to Drive.mat for backup
%Convert variables into structure Drive and pass to handles to enable sharing to
%different callbacks
w = whos;
for a = 1:length(w)
Drive.(w(a).name) = eval(w(a).name);
end
handles.User = Drive; %Set of Drive variables to be edited by user through GUI
guidata(hObject,handles);
Does just what I wanted, free of evalin. Thank you both again for your input.

Sign in to comment.

 Accepted Answer

Why don't you convert Drive_Matlab to a function that returns its variable as fields of a struct? You can put the save/load trick in that script (now function), or better yet, replace it by a more robust method that doesn't rely on the very slow method of writing to disk and reading from disk.

More Answers (0)

Categories

Asked:

on 31 Jan 2018

Commented:

on 1 Feb 2018

Community Treasure Hunt

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

Start Hunting!