I have an object-oriented MATLAB app that needs a GUI, and I'd like to use GUIDE for the layout (at least). I've tried the manual way, and doing the control positioning is just too painful.
I've noticed that GUIDE is very much procedurally-oriented; it generates M-files that assume they are run from the path and aren't associated with any classes or objects.
Has anyone had experience trying to use GUIDE in an object-oriented way? If it's straightforward, I'd like to do automatic code generation as well, but I'm willing to let GUIDE just generate the .fig file and write the code myself.
When you create a gui with guide, for every button/textbox/graph etc. you put on the pane, it automatically generates the shells for the necessary callbacks, so all you have to do is fill in the code. If you change the name of the widgets (their "tags") or add or delete them, it updates your m-file for you, which is handy.
You can associate your gui with objects; the autogenerated m-file has a function outline that looks like this
function YourGUIName_OpeningFcn(hObject, eventdata, handles, varargin)
you can require that someone pass your gui an object or objects through the varargin. The canonical matlab way to do this is to pass parameter name/value pairs, so the call from the command line would look like
YourGuiName('importantobject', object1);
but you could also (especially if there is just one unique argument) assume varargin{1} is a specific parameter, varargin{2} is a second, and so on
In this case, the call from the command line would be
YourGuiName(object1);
In your openingfcn, you would then add a line like
if (length(varargin) < 1) || ~isa(varargin{1}, 'importantObjectType')
error ('you must pass an importantobject to YourGuiName, see help');
end
myimportantobject = varargin{1}
You now have a choice to make. The canonically correct way to store data in your gui is to put it in the handles structure and then store it with guidata, as in
handles.myobject = varargin{1};
guidata(hObject, handles); %this is just boilerplate
The boilerplate is necessary because, despite its name, handles does not subclass Handle, and is passed by value, not reference. the guidata command sticks handles somewhere associated with the gui figure so you can get it in subsequent callbacks.
The problem with this approach is that when you put a large object in handles, it makes the guidata command take forever. This is true even though MATLAB is not supposed to copy data when passing by value unless absolutely necessary, and it is even true if your object is a Handle, which takes like 4 bytes to pass back and forth. Don't ask me why, but I suspect it has something to do with memory management & garbage collection.
If your gui is taking a while to execute commands, and you use profile and see it hanging on the guidata command, you should just declare your object to be a global and deal with it that way
global YOURGUI_object; %it's not my fault; blame MATLAB
YOURGUI_object = varargin{1};
Then you can just have all your callbacks execute whatever method of YOURGUI_object they need.
Good luck.
Related
MEX is the framework Matlab uses to run C/C++ functions in Matlab (runs faster). In the documentation it says:
input parameters (found in the prhs array) are read-only; do not modify them in your MEX file. Changing data in an input parameter can produce undesired side effects.
Is this simply a warning about how changing a variable passed as a pointer will change that variable even outside of the function (unlike how Matlab works), or is there a more subtle way that this can mess up the Matlab/MEX interface?
Reason I am asking is I specifically want the MEX function to modify the arguments for real.
MATLAB uses lazy copying, which means that when you do b = a, variable b points to the same data as variable a, even though semantically you made a copy. When you now do a(1) = 0, for example, you modify variable a, and MATLAB first makes a copy, so that variable b is not affected by the assignment. This obviously saves a lot of memory, because many copies are made where the copy is not modified.
For example, when calling a function, a copy of input variables are placed in the function’s workspace. sum(a) causes a (lazy) copy of a to be made available inside the function. If the function doesn’t need to modify the variable, a copy is avoided. If it does modify it, then a copy is made so that a is not changed for the caller.
MEX-files work the same way, except that MATLAB cannot detect if you modify the input variable, so it cannot make the copy before you do. Hence the warning. You need to call mxDuplicateArray() to copy the array and make changes to your new copy.
The side effects that the documentation warns about is that the variable in the caller’s workspace is modified, along with all variables that it shares data with. For example imagine you make a MEX-file function modifyIn that modified the input, then:
a = zeros(500);
b = a;
% much later in the code…
modifyIn(b); % update b the way I want!
will very unexpectedly also modify a!
This blog post on Undocumented MATLAB talks about this issue in more detail, and talks about mxUnshareArray(), an undocumented function that you should only use if you are really comfortable with the possible crashes and other issues that could happen. Undocumented functions have a limited shelf life.
I have created several figures in Matlab (using GUIDE) which act as a config-GUI for a model. The idea is that changes made in figure F1 should affect what choices can be made in figure F2, F3, .... However, there are 5 figures, all holding different information, and it is possible to navigate arbitrarily between the figures (push buttons on each figure, to every other figure).
A large issue is that I want only one figure to be open at any point in time. That is, when F1 has started FX, I want F1 to close. Hence, I think it is unsuitable to use global variables. (?)
My issue is that I am simply not capable of holding all the data up to date. Maybe this could be achieved using appdata or guidata, but I cannot wrap my head around it.
Examples:
Since the handles of F1 and F2 differs, passing F1.handles to F2 works (F1.handles shows up in varargin{1} in F2), but I cannot concatenate F1.handles with F2.handles. Hence, I have no apt way of sending F1.handles and F2.handles to F3 (or any other figure). (If this can be achieved in a more simple way, I might be okay with dropping the "arbitrarily navigation feature", but so far I have not been able to make it work.)
Using .mat-files (i.e., write FX.handles to a file and load each file in each Figure) seems such bad practice that I haven't even given it a serious go.
So far, I have not found it necessary to change the data in FN±X from FN, hence I guess the .mat-file approach could work, but my latest idea is using Matlab OOP and pass around a class instead of the handles. I found an old post on the topic (Global (shared) variables in Matlab GUI code behind. Is there better way to do it then using handles structure?) but it links merely to a File Exchange and I am unable to understand how to make it applicable for my use case.
Edit 1: I found this Using GUIDE with object-oriented MATLAB?, and will give it a try, but I am still having a hard time understanding exactly how to use it, since it seems to require using handles anyway.
U can try using global variables to retrieve handles for all the figures created by assigning handles values to a global variable in a structure format. Global variable persists in memory until you close the figures.
I'm working on a fairly complex (for me) GUI in Matlab, made programmatically without GUIDE.
The different but similar ways to organize GUI objects confuse me. Please tell me where my understanding is incorrect, and if they're actually different at all:
What is the functional difference between the two following handles structures:
1) A handles populated by the... handles?... of GUI objects created explicitly with a handles. prefix. The guidata function is used in Callback functions to grab an up-to-date copy of handles and then save it.
handles.button = uicontrol(...);
guidata(handles.fig,handles);
appears in handles as button.
2) A handles populated by the 'Tag' fields of GUI objects in a figure fig. This structure is created, after(?) drawing all of your GUI objects, using guihandles.
button = uicontrol(...'Parent',fig,'Tag','push'...);
handles = guihandles(fig);
appears in handles as push.
The guidata function doesn't seem to save to the handles struct made by guihandles. Is it necessary to instead use handles = guihandles(fig) at the end of every Callback?
Or am I thinking about the second type of structure wrong, and is bothering with the handles. prefix unnecessary altogether? Because creating a new GUI object and immediately entering just
guihandles
into the console shows the new GUI object listed with my old GUI objects. But I see this new object is stored openly in my Workspace, and is not under handles until I use
handles = guihandles;
again.
I apologize if it takes a re-read or two of all of the above to get what I'm asking.
There is no difference between the two handles structures that you mention. Both structures should be the same.
It is necessary to use handles=guihandles(fig); instead of guihandles by itself because you need to tell Matlab where to store the results of the guihandles function. If you do not give it a variable to store the results to on the left hand side of the equals sign, it will store your resulting structure in the ans variable.
It's not necessary to create the handles structure at the end of each callback. You should be able to use guihandles to create your handles structure only as you need it.
In Matlab GUIDE, is there any way in which I can save all my GUIhandles from a GUI.m file so that I can access these handles in a different function (a different .m file altogether, not one of the other callbacks in the GUI.m file)?
Note that I don't want to pass these handles manually to the other functions.
Since you are designing your GUI using GUIDE, any uicontrol object you put on the the current figure (e.g. GUI.fig) will have its handle added automatically to the handles structure, the variable that will be passed around between callbacks. handles is also traditionally used to pass any other program variables between callbacks by adding those variables to the handles structure and saving handles using guidata() function.
The easiest and fastest way to pass handles to external functions is to send it as an input parameter to those functions. For example, if your other external file is called auxiliary.m and contains a function called auxiliary(...), just design auxiliary(...) to accept one extra parameter called handles to receive all figure handles -- plus any other manually added variables. This is exactly the way your GUI.m works right now. Note that GUI.m looks like a single file but it's really a container for a lot of callback functions, where each one of them could be a separate .m file containing a single function of the same name. For example, if you were to cut pushbutton1_Callback(hObject, eventdata, handles) out of GUI.m and paste it in a separate pushbutton1_Callback.m file, your program works the exact same way as long as there is no duplicate files of the same name.
If you still insist on not passing the handles directly to the external function, just save the handles structure and load it in the second .m file:
% inside GUI.m
save('handles.mat', 'handles');
%inside auxiliary.m
load('handles.mat', 'handles');
I recommend the first method since there is no IO overhead and you don't need data persistence.
Use findall(figure_handle);
Example:
F=figure;
H=uicontrol('parent',F,'style','pushbutton');
uihandles=findall(F,'type','uicontrol');
If you don't have the figure handle directly, you can use
uihandles=findall(gcf,'type','uicontrol');
I have a MATLAB GUI that loads to aid in visually pre-processing data. Essentially it prompts the user to adjust the data range, reduce number of data points, etc... all while providing an updated graph. Upon completion of this work, I want to be able to close out the GUI and pass variables from the GUI to another MATLAB function that does the data analysis. I have found lots of information on how to pass information from a function TO and GUI, but not the other way around.
Any help would be greatly appreciated.
Global variables can cause hard to find bugs. The best solution for your problem (where you want to pass the data directly to another function on close) might be to call the analysis function from the Figure Close Request Function. When the figure your GUI is running in is told to close, it will run the code in this function, which can call your analysis function and have access to the GUI's data.
Matlab GUIs are functions: the code exists in a .m file just like other functions. Like regular functions, they can have return values. You can get as fancy as you want messing with the varargout system, or you can simply return a value, structure, or cell array containing whatever you want. Open up the m-file and edit it to return what you want it to.
Note: If you require special processing when the figure is being closed to generate the appropriate return value, you can reimplement the closeRequestFcn as you see fit.
The easy way: you declare as global variable, where variable stores the data that you want to carry from the GUI to the main MATLAB workspace. Then, you also declare the same global variable on the command window. Hereinafter, variable to be accesible from both scopes, the GUI and the main workspace.
You could also use save or any other alternatives as csvwrite or dlmwrite to store the data into a file, but this doesn't seem to be your case.