Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The <a href="http://www.mathworks.com/help/matlab/creating_guis/ways-to-manage-data-in-a-programmatic-gui.html#f13-999769" rel="nofollow noreferrer"><code>UserData</code> property</a> is a useful, but legacy, property of MATLAB objects. The "AppData" suite of methods (i.e. <code>setappdata</code>, <code>getappdata</code>, <code>rmappdata</code>, <code>isappdata</code>, etc.) provide a great alternative to the comparatively more clumsy <code>get/set(hFig,'UserData',dataStruct)</code> approach, IMO. In fact, to manage GUI data, GUIDE employs <strong>the <a href="http://www.mathworks.com/help/matlab/ref/guidata.html" rel="nofollow noreferrer"><code>guidata</code></a> function, which is just a wrapper for the <code>setappdata</code>/<code>getappdata</code> functions</strong>.</p> <p>A couple of advantages of the AppData approach over the <code>'UserData'</code> property that come to mind:</p> <ul> <li><p>More natural interface for multiple heterogeneous properties.</p> <p><strong><code>UserData</code> is limited to a single variable</strong>, requiring you to devise another layer of data oranization (i.e. a struct). Say you want to store a string <code>str = 'foo'</code> and a numeric array <code>v=[1 2]</code>. With <code>UserData</code>, you would need to adopt a struct scheme such as <code>s = struct('str','foo','v',[1 2]);</code> and <code>set/get</code> the whole thing whenever you want either property (e.g. <code>s.str = 'bar'; set(h,'UserData',s);</code>). With <code>setappdata</code>, the process is more direct (and efficient): <code>setappdata(h,'str','bar');</code>.</p></li> <li><p>Protected interface to the underlying storage space.</p> <p>While <code>'UserData'</code> 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 <code>setappdata</code> to change any existing AppData properties, which prevents you from accidentally clobbering the entire contents of <code>'UserData'</code> 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 <code>isappdata</code>, 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).</p></li> </ul> <p>An important difference between the <code>'UserData'</code> and <code>'ApplicationData'</code> properties is that <code>'UserData'</code> is by default <code>[]</code> (an empty array), while <code>'ApplicationData'</code> is natively a struct. This difference, together with the fact that <code>setappdata</code> and <code>getappdata</code> have no M-file implementation (they are built-in), suggests that <strong>setting a named property with <code>setappdata</code> does <em>not</em> require rewriting the entire contents of the data struct</strong>. (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 <code>'ApplicationData'</code> handle graphics property.)</p> <hr> <p><strong>The <code>guidata</code> function is a wrapper to the AppData functions, but it is limited to a single variable, like <code>'UserData'</code></strong>. 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:</p> <pre><code>hFig = ancestor(hObj,'Figure') </code></pre> <p>Also, <a href="http://www.mathworks.com/matlabcentral/answers/102591" rel="nofollow noreferrer">as stated by MathWorks</a>, there are efficiency issues:</p> <blockquote> <p>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.</p> </blockquote> <p>This statement supports my assertion that the entire <code>'ApplicationData'</code> is not rewritten when using <code>setappdata</code> to modify a single named property. (On the other hand, <code>guidata</code> crams the <code>handles</code> structure into a field of <code>'ApplicationData'</code> called <code>'UsedByGUIData_m'</code>, so it is clear why <code>guidata</code> would need to rewrite all of the GUI data when one property is changed).</p> <hr> <p>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 <code>'UserData'</code> or AppData as long as you pass the figure handle.</p> <hr> <p>In summary, if you choose to use handle properties to store and pass data, it is possible to use both <code>guidata</code> to manage graphics handles (not large data) <em>and</em> <code>setappdata</code>/<code>getappdata</code> for actual program data. <strong>They will not overwrite each other</strong> since <code>guidata</code> makes a special <code>'UsedByGUIData_m'</code> field in <code>ApplicationData</code> for the <code>handles</code> structure (unless you make the mistake of using that property yourself!). Just to reiterate, do not directly access <code>ApplicationData</code>.</p> <p><strong>However, if you are comfortable with OOP, it may be cleaner to implement GUI functionality via a class</strong>, with handles and other data stored in member variables rather than handle properties, and callbacks in methods that can exist in <a href="https://stackoverflow.com/questions/9781866/folder-and-folder">separate files under the class or package folder</a>. There is a <a href="http://www.mathworks.com/matlabcentral/fileexchange/33816-example-using-a-matlab-class-to-control-a-gui" rel="nofollow noreferrer">nice example on MATLAB Central File Exchange</a>. This submission demonstrates how passing data is simplified with a class since it is no longer necessary to constantly get and update <code>guidata</code> (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 <code>closerequestfcn</code>, which then calls the <code>delete</code> function of the class. The submission nicely parallels the GUIDE example.</p> <p>Those are the highlights as I see them, but many more details and different ideas are <a href="http://www.mathworks.com/help/matlab/creating_guis/ways-to-manage-data-in-a-programmatic-gui.html" rel="nofollow noreferrer">discussed by MathWorks</a>. See also <a href="http://www.mathworks.com/matlabcentral/answers/102591" rel="nofollow noreferrer">this official answer</a> to <code>UserData</code> vs. <code>guidata</code> vs. <code>setappdata/getappdata</code>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload