Getting Matlab handles events or properties - matlab

The question
How may I get the list of events and properties for a handle of double type, as a figure, axes?
The issue
Matlab documentation says to you to use the WindowButtonDownFcn, WindowButtonMotionFcn, and so on in order to listen to whatever happens at your interface. The issue is that this properties are very limited as the following fact:
Keeping Variables in Scope
When MATLAB evaluates function handles, the same variables are in
scope as when the function handle was created. (In contrast, callbacks
specified as strings are evaluated in the base workspace.) This
simplifies the process of managing global data, such as object
handles, in a GUI.
Yes, this is perfect, if you don't have to redefine, add, or remove callbacks from your ButtonDownFcn, because if you do so, you will lose the other function handles variable scopes, as you are declaring them at a new scope which may will certainly not contain your so needed variables.
So one way would be to listen to the events themselves, not to properties that are called when the events are actived, and by doing so, you will not have to bother to redeclare your ButtonDownFcn and how to keep your variables at scope, because the other solutions are very slow to implement!. If I could listen to the events directly, as I do with handle.listener or addlistener matlab listening tools, I would not have to bother with that.
One good approach already known
One of the best solutions it seems is this FEX, which empowers the weak matlab WindowButtonDownFcn, WindowButtonDownFcn and whatever properties "listeners" function matlab has, so that you can have any amounts of functions listening to changes at the your graphical interface without having to care if your other functions handles will lose their scope variables.
With this I don't need to get the matlab events as it wrappers everything for me. But it still amuses me that matlab lead your users to use a broken feature instead of documenting the better approach and lead people to wrap everything around so that they can use things as they should be.
Information that may be useful.
I know about the meta.class that will give me all the properties, events and so on that a class have. For one class I have that inherits from a handle:
>> EventMeta = ?Event
EventMeta =
class with properties:
Name: 'Event'
Description: ''
DetailedDescription: ''
Hidden: 0
Sealed: 0
Abstract: 0
ConstructOnLoad: 0
HandleCompatible: 1
InferiorClasses: {0x1 cell}
ContainingPackage: []
PropertyList: [64x1 meta.property]
MethodList: [29x1 meta.method]
EventList: [2x1 meta.event]
EnumerationMemberList: [0x1 meta.EnumeratedValue]
SuperclassList: [1x1 meta.class]
with that meta I can get the EventList from my Event class, which are:
>> EventMeta.EventList.Name
ans =
attemptToClick
ans =
ObjectBeingDestroyed
Well, this is not that great thing in this case, since I have implemented it and I know the events it has because I have the source. The thing is, if I can get the metaclass of a figure (if that is possible), I could have access to its implemented Events if they are available at the matlab.

Under the hood, Handle Graphics (HG) are implemented using the undocumented UDD mechanism, not the usual classdef-style OOP exposed to the user.
That's why you cant directly use the meta.class system to get meta-information on such handles.
As you already found out on Yair Altman's blog, there are undocumented ways to listen to events:
fig = hg.figure(); plot(rand(100,1))
lh = handle.listener(fig, 'WindowButtonDownEvent',#(~,~)disp('clicked'));
If you already have an existing HG object handle (represented with a numeric handle), use handle to convert it to a UDD handle:
f = figure();
fig = handle(f);
and yes I know, the term handle is quite overloaded in MATLAB and may refer to many things

As I was improving my question, I managed to find an answer for this (unfortunately it seems that I haven't seem them before at my searchs, and what's worse, some of the links I've opened before…)
Here the undocummented matlab blog shows how to get the handles from a matlab handle object. And it seems that there was already a question about this made at 2011 about this issue here in stackoverflow, and properly answered by #gnovice. The answer is:
>> get(get(classhandle(handle(gcf)),'Events'),'Name')
ans =
'SerializeEvent'
'FigureUpdateEvent'
'ResizeEvent'
'WindowKeyReleaseEvent'
'WindowKeyPressEvent'
'WindowButtonUpEvent'
'WindowButtonDownEvent'
'WindowButtonMotionEvent'
'WindowPostChangeEvent'
'WindowPreChangeEvent'
I still would like to call your attention to the FEX as another good solution that may give you better possibilities for working with the graphical components offered by matlab.
Usage example:
>> k=handle.listener(gcf,'WindowButtonMotionEvent','disp(''MOVEMENT DETECTED!!'')');
>> MOVEMENT DETECTED!! % When you move the mouse on the figure
>> MOVEMENT DETECTED!!
>> MOVEMENT DETECTED!!
>> MOVEMENT DETECTED!!
>> MOVEMENT DETECTED!!
>> MOVEMENT DETECTED!!
>> delete(k)

Try using get:
fig = gcf();
get(fig)

I don't know how to do this. I can provide some sample code to demonstrate what I think is being asked. This is a relatively new (therefore unused) Matlab feature:
hh = handle(gca);
lsnr = addlistener(hh,'XLim','PreGet',#(~,~)disp('<<<Getting XLIM values>>>'))
To see the listener in action
>> get(hh,'XLim')
<<<Getting XLIM values>>>
ans =
0 1
I think the question is how to get lsnr from gca if the value was not stored.
I can't find a way.

Related

What's the complete structure of a figure handle object?

Mathworks has done it again: my ancient R2012 (as bestowed by my company) returns a nice set of doubles identifying the figure window numbers in response to
currhandles=findall(0,'type','figure');
Now I got a fellow remotely IM-ing me 'cause the code I gave him fails under R2015 because findall now returns a structure for the figure handle. I can't play w/ his system (no RDC) and the mathworks documentation pages don't appear to specify the elements of the figure handle structure. In particular, I'd like to know if I can still retrieve the figure window number. Anyone know?
Of course.
currhandles(:).Number
will return all numbers as a comma-separated list.
Or specify a number you want:
currhandles(1).Number
The order appears to be the inverse order of initialization.
Alternatively you can define two anonymous functions to get an array directly:
figure(1); figure(2); figure(42);
getNumbers = #(x) [x.Number];
getFigureNumbers = #() getNumbers([findall(0,'type','figure')]);
getFigureNumbers()
ans =
42 2 1

Graphic object handle array in embedded matlab function in Simulink in R2014a or newer

For debugging, I have some plots of vectors in an embedded matlab function in Simulink. Up to Matlab R2013b, everything works just fine with the following minimum example code:
function fcn
%#minimum example for plot within for-loop of embedded matlab function
coder.extrinsic('delete');
coder.extrinsic('quiver');
coder.extrinsic('gobjects');
numSteps=4;
persistent hFig;
persistent hVector;
if isempty(hFig)
hFig = figure;
hold on;
hVector=zeros(numSteps,1);
hVector=gobjects(numSteps,1);
for i=1:numSteps
hVector(i) = quiver(0,0,0,0);
end
end
set(0, 'CurrentFigure', hFig);
delete(hVector);
for i=1:numSteps
startInc=[1 1;1 1].*i;
endInc=[2 3;2 -3].*i;
hVector(i) = quiver(startInc(1,:),startInc(2,:),endInc(1,:),endInc(2,:));
end
For the handle array hVector, an initialization is necessary due to its use in the for-loop. However, for an Initialization of a graphics handle object, the function gobjects is needed and in turn the initialization as double with zeros(numSteps,1) becomes necessary, since matlab cannot correctly determine the data type of an output of an extrinsic function.
As I said, this code snippet works just fine if copied to an embedded matlab function block in simulink without anything else in the model.
My problem: Mathworks changed a lot of the plotting functions in R2014a, one of the changes being the datatype of the graphics handles which are no of type quiver for my quiver plot. Thus, the initialization with zeros(numSteps,1) initializes the wrong data type for the handle array. However leaving it out still does not work, because of the problem mentioned above. Neither does a init loop or anything similar compile without errors.
I'd greatly appreciate any help on that issue.
You can try to remove the gobject initialisation and use double() to wrap your call to any matlab graphic object. Ex:
hVector(i) = double( quiver(startInc(1,:),startInc(2,:),endInc(1,:),endInc(2,:)) ) ;
I suggest reading Loren's article about the compatibility issues which can arise when switching to HG2 versions of Matlab.
A quick quote from it which apply more to your issue:
Graphics Functions Return Objects, not Numeric Handles
Prior to R2014b, you could store a set of handles to graphics objects
in an array and then add some numeric data to that array. In R2014b,
that will cause an error.
[...]
If you find yourself really stuck, it is possible to cast object
handles to numeric handles using the double function. You can then
cast the number back to an object handle using the handle function. We
don't recommend this as a long term solution. Be aware that we may
choose to remove this feature in a future version of MATLAB. If we do,
we'll let you know in advance.
Now if you really have to use this solution, note that both functions works on single elements but also on arrays. So
hVector_HG = handle( hVector_Num ) ; %// works if "hVector_Num" is an array of numeric handles
%// and ...
hVector_Num = double( hVector_HG ) ; %// works if "hVector_HG" is an array of HG2 graphic handles
That may simplify the round trips between a format or another if they often become necessary.
Edit:
I put this at the bottom of the post for the moment because the beginning is already accepted answer but please try the following and let me know if it works. It may solve your problem in a better (more future-proof) way.
Another way to initialise an array of handle of a given graphic object is to create one (empty is good enough) and replicate it. For example:
hqNaN = quiver(NaN,NaN) ; %// create an empty quiver
hVector = repmat( hqNaN , numSteps , 1 ) ; %// replicate it in an array
will give you an array hVector containing numSteps HG2 graphic object handles. At this point they all point to the very same object but it is perfectly legal to overwrite each element with a handle of the same type. So a later :
hVector(i) = quiver( ... , etc ... ) ; %// overwrite handle "i" with a new quiver plot handle
will (should) work without problem.
A few things to take care with this approach:
where will the empty quiver be created ?
you may already have a "current" figure and you don't want it to be messed up. If not a new empty plot will be created. So to make sure the empty quiver do not cause problem (just a flicker on the screen), you could wrap it this way:
figure ; hqNaN = quiver(NaN,NaN) ; close(gcf) ;
or you can also park it in a figure (it will be invisible anyway) in case you need to re-use a handle of this type for other array initialisation. Just don't forget that once you close the figure it is on, or you delete the graphic object, the hqNaN variable is still there but it is not the same type of handle any more (so not useful to replicate if you want this type exactly).
What if you do not overwrite all you initial handle array ?
Remember all the initial handles of the array point to the same graphic object. So in case your array contains 12 elements but let's say by mistake you only overwrite 10 of them, then 2 elements will be handles pointing to the same object (which you may already have deleted)). This means that calling:
delete(hVector)
will throw you the annoying:
Error using handle.handle/delete. Invalid or deleted object.
gna gna gna ... luckily you can easily prepare for that by programming defensively and using instead:
delete( hVector(ishandle(hVector)) )
Matlab will do the check automatically and only delete the right handles.

Is it possible to enforce input argument data types in MATLAB?

I would like to ensure that the input arguments to a user-defined MATLAB function (contained in an m-file) are of a certain type. I understand that MATLAB automatically assigns data types to variables (to the liking of some and the dismay of others), but I would like to know if there is an option of "strict data typing" in MATLAB, or something of the sort, especially for input arguments for a user-defined function.
I found a helpful explanation of MATLAB's "fundamental classes" (data types) at these two webpages:
http://www.mathworks.com/help/matlab/matlab_prog/fundamental-matlab-classes.html
http://www.mathworks.com/help/matlab/data-types_data-types.html
However, I have been unable to find an answer to the question of strict data typing, particularly for function input arguments. I thought it would be a pretty basic question that already had been answered in numerous places, but after extensive searching I have not yet found a conclusive answer. For now, I have been manually checking the data type using the is[TYPE]() functions and displaying an error message if it does not comply, though this seems sloppy and I wish I could just get MATLAB to enforce it for me.
Below is an example of a function in which I would like to specify the input argument data type. It resides in a file called strict_data_type_test.m in MATLAB's current path. In this function, I would like to force the variable yes_or_no to be of MATLAB's logical data type. I know I can use the islogical() function to manually check, but my question is if it is possible to have MATLAB enforce it for me. I also know that any non-zero double evaluates to true and a zero evaluates to false, but I want to force the user to send a logical to make sure the wrong argument was not sent in by accident, for example. Here is the example function:
function y = strict_data_type_test( x, yes_or_no )
% manual data type check can go here, but manual check is not desirable
if (yes_or_no)
y = 2 .* x;
else
y = -5 .* x;
end
end
Adding the data type before the input argument variable name (like in most programming languages) treats the data type text as another variable name instead of a data type identifier. From that it would seem that strict data typing is not possible in MATLAB by any means, but maybe one of you many gurus knows a useful trick, feature, or syntax that I have not been able to find.
validateattributes might also work for you, if there is an appropriate attribute for your case. For example if you want to enforce that yes_or_no is a logical scalar, you could try:
validateattributes(yes_or_no,{'logical'},{'scalar'})
Otherwise maybe an attribute like 'nonempty'.
I've gotten some great responses so I can't pick just one as the "accepted answer", but to summarize what I've learned from you all so far:
No, MATLAB does not have built-in strict data typing for function input arguments
MATLAB compiles the code before running, so manual validation checking should not be very taxing on performance (the profiler can be used to assess this)
Many helpful methods of doing the manual validation checking exist, listed here in order of most relevant to least relevant for what I was trying to do:
inputParser class
validateattributes()
Error/exception handling (throw(), error(), assert(), etc.)
MATLAB's built-in state detection functions (a.k.a predicate functions)
I can look through some MathWorks-provided MATLAB functions (or Statistics toolbox functions) for ideas on how to validate input arguments by typing edit followed by the function name. Two suggested functions to look at are normpdf() (from the Statistics toolbox) and integral(). Some other functions I found helpful to look at are dot() and cross().
Other thoughts:
It would appear that the inputParser class was the overall concensus on the most professional way to validate input arguments. It was noted on a related (but not duplicate) stackoverflow post that the newer MathWorks functions tend to make use of this class, suggesting that it may be the best and most up-to-date choice.
Since the MathWorks-provided MATLAB functions do not appear to enforce strict input argument data typing, this further suggests that even if it was possible to do so, it may not be a recommended approach.
MATLAB seems to regard "error handling" and "exception handling" as two different concepts. For example, here are two links to MATLAB's Documentation Center that show how MathWorks considers "error handling" and "exception handling" differently: MathWorks Documentation Center article on Error Handling, MathWorks Documentation Center article on Exception Handling. A relevant StackOverflow post has been made on this topic and can be found here (link). I contacted MathWorks and added some new information about this topic to that post, so if you are interested you may read more by following that link.
Matlab provides an 'inputParser' which allows to check inputs. Besides this you can use assertions:
assert(islogical(yes_or_no),'logical input expected')
To ensure the correct number of input arguments, use narginchk.
btw: Take a look in some Matlab functions like edit integral and check how tmw deals with this.
You may find writing this sort of code tedious or worry that it degrades performance:
if ~islogical(yes_or_no) && ~isscalar(yes_or_no)
error('test:NotLogicalType','Second argument must be logical (Boolean).');
end
if yes_or_no
y = 2 .* x;
else
y = -5 .* x;
end
Recall, however, that Matlab compiles the code before running so even if you need to test many conditions it will be quite fast. Run the profiler to see.
Another option in some cases (maybe not your example) is to use a lazier method. This option lets your code run with whatever inputs were provided, but uses a try/catch block to trap any error:
try
if yes_or_no
y = 2 .* x;
else
y = -5 .* x;
end
catch me
...
error('test:NotLogicalType','Second argument must be logical (Boolean).');
% rethrow(me);
end
The code above would produce an error if yes_or_no was a cell array for example (it will still allow non-Boolean, non-scalar, etc. values for yes_or_no though, but Matlab is often overly permissive). You can then either generate a custom error message, detect, what kind of error was thrown and try something else, etc. Many of the functions in the Statistics toolbox use this approach (e.g., type edit normpdf in your command window) for better or worse.

What's the "right" way to organize GUI code?

I'm working on a fairly sophisticated GUI program to be deployed with MATLAB Compiler. (There are good reasons MATLAB is being used to build this GUI, that is not the point of this question. I realize GUI-building is not a strong suit for this language.)
There are quite a few ways to share data between functions in a GUI, or even pass data between GUIs within an application:
setappdata/getappdata/_____appdata - associate arbitrary data to a handle
guidata - typically used with GUIDE; "store[s] or retrieve[s] GUI data" to a structure of handles
Apply a set/get operation to the UserData property of a handle object
Use nested functions within a main function; basically emulates "globally" scoping variables.
Pass the data back and forth among subfunctions
The structure for my code is not the prettiest. Right now I have the engine segregated from the front-end (good!) but the GUI code is pretty spaghetti-like. Here's a skeleton of an "activity", to borrow Android-speak:
function myGui
fig = figure(...);
% h is a struct that contains handles to all the ui objects to be instantiated. My convention is to have the first field be the uicontrol type I'm instantiating. See draw_gui nested function
h = struct([]);
draw_gui;
set_callbacks; % Basically a bunch of set(h.(...), 'Callback', #(src, event) callback) calls would occur here
%% DRAW FUNCTIONS
function draw_gui
h.Panel.Panel1 = uipanel(...
'Parent', fig, ...
...);
h.Panel.Panel2 = uipanel(...
'Parent', fig, ...
...);
draw_panel1;
draw_panel2;
function draw_panel1
h.Edit.Panel1.thing1 = uicontrol('Parent', h.Panel.Panel1, ...);
end
function draw_panel2
h.Edit.Panel2.thing1 = uicontrol('Parent', h.Panel.Panel2, ...);
end
end
%% CALLBACK FUNCTIONS
% Setting/getting application data is done by set/getappdata(fig, 'Foo').
end
I have previously-written code where nothing is nested, so I ended up passing h back and forth everywhere (since stuff needed to be redrawn, updated, etc) and setappdata(fig) to store actual data. In any case, I've been keeping one "activity" in a single file, and I'm sure this is going to be a maintenance nightmare in the future. Callbacks are interacting with both application data and graphical handle objects, which I suppose is necessary, but that's preventing a complete segregation of the two "halves" of the code base.
So I'm looking for some organizational/GUI design help here. Namely:
Is there a directory structure I ought to be using to organize? (Callbacks vs drawing functions?)
What's the "right way" to interact with GUI data and keep it segregated from application data? (When I refer to GUI data I mean set/getting properties of handle objects).
How do I avoid putting all these drawing functions into one giant file of thousands of lines and still efficiently pass both application and GUI data back and forth? Is that possible?
Is there any performance penalty associated with constantly using set/getappdata?
Is there any structure my back-end code (3 object classes and a bunch of helper functions) should take to make it easier to maintain from a GUI perspective?
I'm not a software engineer by trade, I just know enough to be dangerous, so I'm sure these are fairly basic questions for seasoned GUI developers (in any language). I almost feel like the lack of a GUI design standard in MATLAB (does one exist?) is seriously interfering with my ability to complete this project. This is a MATLAB project that is much more massive than any I've ever undertaken, and I've never had to give much thought to complicated UIs with multiple figure windows, etc., before.
As #SamRoberts explained, the Model–view–controller (MVC) pattern is well-suited as an architecture to design GUIs. I agree that there are not a lot of MATLAB examples out there to show such design...
Below is a complete yet simple example I wrote to demonstrate an MVC-based GUI in MATLAB.
The model represents a 1D function of some signal y(t) = sin(..t..). It is a handle-class object, that way we can pass the data around without creating unnecessary copies. It exposes observable properties, which allows other components to listen for change notifications.
The view presents the model as a line graphics object. The view also contains a slider to control one of the signal properties, and listens to model change notifications. I also included an interactive property which is specific to the view (not the model), where the line color can be controlled using the right-click context menu.
The controller is responsible of initializing everything and responding to events from the view and correctly updating the model accordingly.
Note that the view and controller are written as regular functions, but you could write classes if you prefer fully object-oriented code.
It is a little extra work compared to the usual way of designing GUIs, but one of the advantages of such architecture is the separation of the data from presentation layer. This makes for a cleaner and more readable code especially when working with complex GUIs, where code maintenance becomes more difficult.
This design is very flexible as it allows you to build multiple views of the same data. Even more you can have multiple simultaneous views, just instantiate more views instances in the controller and see how changes in one view are propagated to the other! This is especially interesting if your model can be visually presented in different ways.
In addition, if you prefer you can use the GUIDE editor to build interfaces instead of programmatically adding controls. In such a design we would only use GUIDE to build the GUI components using drag-and-drop, but we would not write any callback functions. So we'll only be interested in the .fig file produced, and just ignore the accompanying .m file. We would setup the callbacks in the view function/class. This is basically what I did in the View_FrequencyDomain view component, which loads the existing FIG-file built using GUIDE.
Model.m
classdef Model < handle
%MODEL represents a signal composed of two components + white noise
% with sampling frequency FS defined over t=[0,1] as:
% y(t) = a * sin(2pi * f*t) + sin(2pi * 2*f*t) + white_noise
% observable properties, listeners are notified on change
properties (SetObservable = true)
f % frequency components in Hz
a % amplitude
end
% read-only properties
properties (SetAccess = private)
fs % sampling frequency (Hz)
t % time vector (seconds)
noise % noise component
end
% computable dependent property
properties (Dependent = true, SetAccess = private)
data % signal values
end
methods
function obj = Model(fs, f, a)
% constructor
if nargin < 3, a = 1.2; end
if nargin < 2, f = 5; end
if nargin < 1, fs = 100; end
obj.fs = fs;
obj.f = f;
obj.a = a;
% 1 time unit with 'fs' samples
obj.t = 0 : 1/obj.fs : 1-(1/obj.fs);
obj.noise = 0.2 * obj.a * rand(size(obj.t));
end
function y = get.data(obj)
% signal data
y = obj.a * sin(2*pi * obj.f*obj.t) + ...
sin(2*pi * 2*obj.f*obj.t) + obj.noise;
end
end
% business logic
methods
function [mx,freq] = computePowerSpectrum(obj)
num = numel(obj.t);
nfft = 2^(nextpow2(num));
% frequencies vector (symmetric one-sided)
numUniquePts = ceil((nfft+1)/2);
freq = (0:numUniquePts-1)*obj.fs/nfft;
% compute FFT
fftx = fft(obj.data, nfft);
% calculate magnitude
mx = abs(fftx(1:numUniquePts)).^2 / num;
if rem(nfft, 2)
mx(2:end) = mx(2:end)*2;
else
mx(2:end -1) = mx(2:end -1)*2;
end
end
end
end
View_TimeDomain.m
function handles = View_TimeDomain(m)
%VIEW a GUI representation of the signal model
% build the GUI
handles = initGUI();
onChangedF(handles, m); % populate with initial values
% observe on model changes and update view accordingly
% (tie listener to model object lifecycle)
addlistener(m, 'f', 'PostSet', ...
#(o,e) onChangedF(handles,e.AffectedObject));
end
function handles = initGUI()
% initialize GUI controls
hFig = figure('Menubar','none');
hAx = axes('Parent',hFig, 'XLim',[0 1], 'YLim',[-2.5 2.5]);
hSlid = uicontrol('Parent',hFig, 'Style','slider', ...
'Min',1, 'Max',10, 'Value',5, 'Position',[20 20 200 20]);
hLine = line('XData',NaN, 'YData',NaN, 'Parent',hAx, ...
'Color','r', 'LineWidth',2);
% define a color property specific to the view
hMenu = uicontextmenu;
hMenuItem = zeros(3,1);
hMenuItem(1) = uimenu(hMenu, 'Label','r', 'Checked','on');
hMenuItem(2) = uimenu(hMenu, 'Label','g');
hMenuItem(3) = uimenu(hMenu, 'Label','b');
set(hLine, 'uicontextmenu',hMenu);
% customize
xlabel(hAx, 'Time (sec)')
ylabel(hAx, 'Amplitude')
title(hAx, 'Signal in time-domain')
% return a structure of GUI handles
handles = struct('fig',hFig, 'ax',hAx, 'line',hLine, ...
'slider',hSlid, 'menu',hMenuItem);
end
function onChangedF(handles,model)
% respond to model changes by updating view
if ~ishghandle(handles.fig), return, end
set(handles.line, 'XData',model.t, 'YData',model.data)
set(handles.slider, 'Value',model.f);
end
View_FrequencyDomain.m
function handles = View_FrequencyDomain(m)
handles = initGUI();
onChangedF(handles, m);
hl = event.proplistener(m, findprop(m,'f'), 'PostSet', ...
#(o,e) onChangedF(handles,e.AffectedObject));
setappdata(handles.fig, 'proplistener',hl);
end
function handles = initGUI()
% load FIG file (its really a MAT-file)
hFig = hgload('ViewGUIDE.fig');
%S = load('ViewGUIDE.fig', '-mat');
% extract handles to GUI components
hAx = findobj(hFig, 'tag','axes1');
hSlid = findobj(hFig, 'tag','slider1');
hTxt = findobj(hFig, 'tag','fLabel');
hMenu = findobj(hFig, 'tag','cmenu1');
hMenuItem = findobj(hFig, 'type','uimenu');
% initialize line and hook up context menu
hLine = line('XData',NaN, 'YData',NaN, 'Parent',hAx, ...
'Color','r', 'LineWidth',2);
set(hLine, 'uicontextmenu',hMenu);
% customize
xlabel(hAx, 'Frequency (Hz)')
ylabel(hAx, 'Power')
title(hAx, 'Power spectrum in frequency-domain')
% return a structure of GUI handles
handles = struct('fig',hFig, 'ax',hAx, 'line',hLine, ...
'slider',hSlid, 'menu',hMenuItem, 'txt',hTxt);
end
function onChangedF(handles,model)
[mx,freq] = model.computePowerSpectrum();
set(handles.line, 'XData',freq, 'YData',mx)
set(handles.slider, 'Value',model.f)
set(handles.txt, 'String',sprintf('%.1f Hz',model.f))
end
Controller.m
function [m,v1,v2] = Controller
%CONTROLLER main program
% controller knows about model and view
m = Model(100); % model is independent
v1 = View_TimeDomain(m); % view has a reference of model
% we can have multiple simultaneous views of the same data
v2 = View_FrequencyDomain(m);
% hook up and respond to views events
set(v1.slider, 'Callback',{#onSlide,m})
set(v2.slider, 'Callback',{#onSlide,m})
set(v1.menu, 'Callback',{#onChangeColor,v1})
set(v2.menu, 'Callback',{#onChangeColor,v2})
% simulate some change
pause(3)
m.f = 10;
end
function onSlide(o,~,model)
% update model (which in turn trigger event that updates view)
model.f = get(o,'Value');
end
function onChangeColor(o,~,handles)
% update view
clr = get(o,'Label');
set(handles.line, 'Color',clr)
set(handles.menu, 'Checked','off')
set(o, 'Checked','on')
end
In the controller above, I instantiate two separate but synchronized views, both representing and responding to changes in the same underlying model. One view shows the time-domain of the signal, and another shows the frequency-domain representation using FFT.
The UserData property is a useful, but legacy, property of MATLAB objects. The "AppData" suite of methods (i.e. setappdata, getappdata, rmappdata, isappdata, etc.) provide a great alternative to the comparatively more clumsy get/set(hFig,'UserData',dataStruct) approach, IMO. In fact, to manage GUI data, GUIDE employs the guidata function, which is just a wrapper for the setappdata/getappdata functions.
A couple of advantages of the AppData approach over the 'UserData' property that come to mind:
More natural interface for multiple heterogeneous properties.
UserData is limited to a single variable, requiring you to devise another layer of data oranization (i.e. a struct). Say you want to store a string str = 'foo' and a numeric array v=[1 2]. With UserData, you would need to adopt a struct scheme such as s = struct('str','foo','v',[1 2]); and set/get the whole thing whenever you want either property (e.g. s.str = 'bar'; set(h,'UserData',s);). With setappdata, the process is more direct (and efficient): setappdata(h,'str','bar');.
Protected interface to the underlying storage space.
While 'UserData' is just a regular handle graphics property, the property containing the application data is not visible, although it can be accessed by name ('ApplicationData', but don't do it!). You have to use setappdata to change any existing AppData properties, which prevents you from accidentally clobbering the entire contents of 'UserData' while trying to update a single field. Also, before setting or getting an AppData property, you can verify the existence of a named property with isappdata, which can help with exception handling (e.g. run a process callback before setting input values) and managing the state of the GUI or the tasks which it governs (e.g. infer state of a process by existence of certain properties and update GUI appropriately).
An important difference between the 'UserData' and 'ApplicationData' properties is that 'UserData' is by default [] (an empty array), while 'ApplicationData' is natively a struct. This difference, together with the fact that setappdata and getappdata have no M-file implementation (they are built-in), suggests that setting a named property with setappdata does not require rewriting the entire contents of the data struct. (Imagine a MEX function that performs a in-place modification of a struct field - an operation MATLAB is able to implement by maintaining a struct as the underlying data representation of the 'ApplicationData' handle graphics property.)
The guidata function is a wrapper to the AppData functions, but it is limited to a single variable, like 'UserData'. That means you have to overwrite the entire data structure containing all of your data fields to update a single field. A stated advantage is that you can access the data from a callback without needing the actual figure handle, but as far as I am concerned, this is not a big advantage if you are comfortable with the following statement:
hFig = ancestor(hObj,'Figure')
Also, as stated by MathWorks, there are efficiency issues:
Saving large amounts of data in the 'handles' structure can sometimes cause a considerable slowdown, especially if GUIDATA is often called within the various sub-functions of the GUI. For this reason, it is recommended to use the 'handles' structure only to store handles to graphics objects. For other kinds of data, SETAPPDATA and GETAPPDATA should be used to store it as application data.
This statement supports my assertion that the entire 'ApplicationData' is not rewritten when using setappdata to modify a single named property. (On the other hand, guidata crams the handles structure into a field of 'ApplicationData' called 'UsedByGUIData_m', so it is clear why guidata would need to rewrite all of the GUI data when one property is changed).
Nested functions require very little effort (no auxiliary structures or functions needed), but they obviously limit the scope of data to the GUI, making it impossible for other GUIs or functions to access that data without returning values to the base workspace or a common calling function. Obviously this prevents you from splitting sub-functions out into separate files, something that you can easily do with 'UserData' or AppData as long as you pass the figure handle.
In summary, if you choose to use handle properties to store and pass data, it is possible to use both guidata to manage graphics handles (not large data) and setappdata/getappdata for actual program data. They will not overwrite each other since guidata makes a special 'UsedByGUIData_m' field in ApplicationData for the handles structure (unless you make the mistake of using that property yourself!). Just to reiterate, do not directly access ApplicationData.
However, if you are comfortable with OOP, it may be cleaner to implement GUI functionality via a class, with handles and other data stored in member variables rather than handle properties, and callbacks in methods that can exist in separate files under the class or package folder. There is a nice example on MATLAB Central File Exchange. This submission demonstrates how passing data is simplified with a class since it is no longer necessary to constantly get and update guidata (members variables are always up to date). However there is the additional task of managing cleanup on exit, which the submission accomplishes by setting the figure's closerequestfcn, which then calls the delete function of the class. The submission nicely parallels the GUIDE example.
Those are the highlights as I see them, but many more details and different ideas are discussed by MathWorks. See also this official answer to UserData vs. guidata vs. setappdata/getappdata.
I disagree that MATLAB is not good for implementing (even complex) GUIs - it's perfectly fine.
However, what is true is that:
There are no examples in the MATLAB documentation of how to implement or organize a complex GUI application
All the documentation examples of simple GUIs use patterns that do not scale well at all to complex GUIs
In particular, GUIDE (the built-in tool for auto-generating GUI code) generates terrible code that is a dreadful example to follow if you're implementing something yourself.
Because of these things, most people are only exposed to either very simple or really horrible MATLAB GUIs, and they end up thinking MATLAB is not suitable for making GUIs.
In my experience the best way to implement a complex GUI in MATLAB is the same way as you would in another language - follow a well-used pattern such as MVC (model-view-controller).
However, this is an object-oriented pattern, so first you'll have to get comfortable with object-oriented programming in MATLAB, and particularly with the use of events. Using an object-oriented organization for your application should mean that all the nasty techniques you mention (setappdata, guidata, UserData, nested function scoping, and passing back and forth multiple data copies) are not necessary, as all the relevant things are available as class properties.
The best example I know of that MathWorks has published is in this article from MATLAB Digest. Even that example is very simple, but it gives you an idea of how to start off, and if you look into the MVC pattern it should become clear how to extend it.
In addition, I typically make heavy use of package folders to organize large codebases in MATLAB, to ensure there are no name clashes.
One final tip - use the GUI Layout Toolbox, from MATLAB Central. It makes many aspects of GUI development much easier, particularly implementing automatic resize behaviour, and gives you several additional UI elements to use.
Hope that helps!
Edit: In MATLAB R2016a MathWorks introduced AppDesigner, a new GUI-building framework intended to gradually replace GUIDE.
AppDesigner represents a major break with previous GUI-building approaches in MATLAB in several ways (most deeply, the underlying figure windows generated are based on an HTML canvas and JavaScript, rather than Java). It is another step along a road initiated by the introduction of Handle Graphics 2 in R2014b, and will doubtless evolve further over future releases.
But one impact of AppDesigner on the question asked is that it generates much better code than GUIDE did - it's pretty clean, object-oriented, and suitable to form the basis of an MVC pattern.
I am very uncomfortable with the way GUIDE produces functions. (think about cases where you'd like to call one gui from another)
I would strongly suggest you write your code object oriented using handle classes. That way you can do fancy stuffs (e.g. this) and not get lost. For organizing code you have the + and # directories.
I don't think structuring GUI-code is fundamentally different from non-GUI code.
Put things that belong together, together at some location.
Like helper-functions that might go into a util or helpers directory. Depending on the content, maybe make it a package.
Personally I don't like the "one function one m-file" philosophy some MATLAB people have.
Putting a function like:
function pushbutton17_callback(hObject,evt, handles)
some_text = someOtherFunction();
set(handles.text45, 'String', some_text);
end
into a seperate file simply makes no sense, when there's no scenario whatsoever you'd call this from somewhere else then from your own GUI.
You can however build the GUI itself in a modular way, by e.g. creating certain components by simply passing the parent container:
handles.panel17 = uipanel(...);
createTable(handles.panel17); % creates a table in the specified panel
This also simplifies testing of certain sub-components - you could simply call createTable on an empty figure and test certain functionalities of the table without loading the full application.
Just two additional items I started using when my application became increasingly larger:
Use listeners over callbacks, they can simplify GUI programming significantly.
If you have really large data (such as from a database, etc.) it might be worthwhile implementing a handle-class holding this data.
Storing this handle somewhere in the guidata/appdata significantly improves get/setappdata performance.
Edit:
Listeners over callbacks:
A pushbutton is bad example. Pushing a button usually only triggers on certain action, here callbacks are fine imho.
A main advantage in my case e.g. was that programmatically changing text/popup lists does not trigger callbacks, while listeners on their String or Value property are triggered.
Another example:
If there's some central property (e.g. like some source of inputdata) that multiple components in the application depend on, then using listeners is very convenient to assure that all components are notified if the property changes.
Every new component "interested" in this property can simply add it's own listener, so there's no need to centrally modify the callback.
This allows for a much more modular design of the GUI components and makes adding/removing of such components easier.

How to store results from a callback function?

I have created a MATLAB gui in order to run a certain simulation.
In this gui is one button to start the simulation. This button callback function will then excecute the calculations. This will off course result in a dataset with the results.
Furthermore in the interface is a plot area, and a selectbox to switch between different graphs, in order to show different aspects of the simulation results. Therefore the results must be available for other functions in the gui as well. This is a problem, since the callback function has no output
Two solutions I can think of are storing the dataset in a MAT-file, or using global variables. The first solution seems not really correct to me, and furthermore I learned that global variabeles must be avoided if possible. So what is the best solution here?
you could create a user defined class inheriting from the handle class that defines your callbacks, your callbacks then execute from "inside" the handle class instance
classdef mySimulation < handle
properties
hFigure
mySimResults
end
methods
function this = mySimulation(varargin)
hFigure = figure;
...
<build figure components>
...
end
function myButtonCallback(this, src, evnt)
this.mySimResults = runMySimulation;
...
<update plot etc>
end
function mySelectBoxCallback(this, src, evnt)
...
<update plots>
end
end
end
MATLAB offers certain functions for this. There is the function guidata, which can store one variable. This can for instance be used to pass around your gui handles. Furthermore there are the functions setappdata and getappdata. These functions are the way to transfer data between functions, and couple variables to a figure handle.
More information on the different methods can be read here.
This is supposed to be semantically more correct then using global variables. However, I am still curious why. Any comments?