Tips & Tricks
Follow


Rik

How to create a GUI

Rik on 4 Oct 2019
Latest activity Reply by Rik on 4 Nov 2022

There are multiple ways to create a graphical user interface (GUI) in Matlab. Which method is the best depends on multiple factors: the complexity of the project, to what extent it should be a long-term solution, on what releases your GUI should work, your available time, your skill level, and probably other factors I'm forgetting.
To keep the thread clear I'll attempt to provide a short outline a few ways in this question, and leave the details for the answers. (@anyone with editing privileges: feel free to update the section below if I missed something important and am slow in editing this question)
---------------------------------------------------------------------------------------------------
GUIDE
GUIDE is probably the first tool new users will encounter. It is very useful for quickly putting something together, but it is otherwise fairly limited. It requires maintaining (and distributing) both a .m and a .fig file. Note that the GUIDE environment will be removed in a future release. After GUIDE is removed, existing GUIDE apps will continue to run in Matlab but they will not be editable in GUIDE. If you're starting a new GUI, don't use GUIDE. If you're updating an existing GUIDE GUI, migrate it to AppDesigner. In R2021a the first step for this removal was taken: all templates except the blank template have been removed.
GUILT
Although I haven't had a detailed look myself, it seems a list like this is not complete without at least mentioning the GUI Layout Toolbox, which is available on the file exchange and offers a lot of customization options.
Programmatic GUIs
You can bypass GUIDE and use the normal figures and functions like uicontrol to build GUIs from code. This makes the design less visual, but more flexible for future additions.
App Designer
The official successor to GUIDE, AppDesigner is not based on functions, but works similar to a class. It uses uifigure and mostly uses graphical elements that are incompatible with 'normal' GUIs that are created with a figure (or .fig).
Dr. Kelsey Joy
Dr. Kelsey Joy on 14 Apr 2022
Here's a sample code I just published of a GUI Tic Tac Toe game created without GUIDE: https://www.mathworks.com/matlabcentral/fileexchange/110100-tic-tac-toe-game-gui-without-guide-pvp-or-pvc-option
I also have a collection of YouTube videos posted with it where I walk through creating figures, uicontrols, callback functions, etc.
Rik
Rik on 4 Nov 2022
@Ravikiran Anapagaddi that is a completely separate question.
Have a read here and here. Did you even google how to do this?
Ravikiran Anapagaddi
Ravikiran Anapagaddi on 4 Nov 2022
Can you please let me know the proceedure to convert *.mlapp
file into standardalone application where I want to run application without having MATLAB (by installing runtime compilier)
Adam
Adam on 10 Feb 2020
One thing I haven't tried yet, but really need to with the looming death of javacomponent, is doing a programmatic class-based UI based on a uifigure. But this addition from R2018b hopefully makes this a feasible way forward for future GUIs:
As mentioned above, I make heavy use of the GUI Layout Toolbox and would hate to create a complex UI without it now, but the uigridlayout does look like a contender to replace this for use with uifigure, provided Mathworks provide enough of the components I would want to replace using java-based ones (most notably a range slider, though that can be worked around with an ugly 2 slider affair).
I'll no doubt try appdesigner from time to time again, but until or unless the editor behaves the same as the main editor for coding and the entire code for the UI is editable, it's still a non-starter for me.
Rik
Rik on 30 Jan 2020
Partly inspired by Adam's comment, I created a class wrapping a GUI as an answer to this question. This example contains a radiobutton, an OK button (which only closes the figure), and a cancel button (which reverts all properties back to the initial value and closes the figure). This should show-case the main things you can do with a class-based programmatic GUI.
It style is a subset of programmatic GUIs, so most if not all of the advice in my other answer applies here as well.
classdef MyClass < handle
%Just like with a normal function, the doc goes here, otherwise
%help('MyClass') will grab the help text from the constructor.
properties %public properties
Radio_Selected=false;%set initial value (optional)
end
properties (Access = private) %hide implementation details
fig
defaults=struct;
end
methods
function obj=MyClass
%Contructor method, this creates the GUI
obj.fig=figure('Units','Normalized','Position',[.3 .3 .3 .3],...
'menubar', 'none');
%Store the current value of the public properties as defaults
props=properties(obj);
for n=1:numel(props)
obj.defaults.(props{n})=obj.(props{n});
end
%You can either set a private method as a callback, or use an
%embedded function. Of course an evaluated char also works.
uicontrol('Units','Normalized','Position',[.1 .1 .35 .25],...
'String', 'OK',...
'Callback','close(gcbf)');
uicontrol('Units','Normalized','Position',[.55 .1 .35 .25],...
'String', 'CANCEL',...
'Callback',@(h,e) obj.Callback_CANCEL);
uicontrol('Style','radiobutton', ...
'Units','Normalized','Position', [.1 .5 .8 .4],...
'String','Some radio button',...
'Callback',@(h,e) Callback_radio(h,obj));
end
end
methods( Access = private )
function Callback_CANCEL(obj)
%Revert to defaults and close figure
props=properties(obj);
for n=1:numel(props)
obj.(props{n})=obj.defaults.(props{n});
end
close(obj.fig)
end
end
end
function Callback_radio(h,class_obj)
%Set the class property so it can be retrieved after the GUI has closed
class_obj.Radio_Selected=h.Value;
end
Rik
Rik on 30 Jan 2020
Ah, so that is the 'correct' way to do it, I have edited my example to include that as an option as well. While writing/debugging I was already wondering how I could best set a method as the callback function. I suspect this syntax works at least since R2016b, as that is the release where you could put local functions in a script as well, but I have not tested the extent myself.
Adam
Adam on 30 Jan 2020
I would generally use class methods for callback functions, but I guess standalone function with the object explicitly passed in like any other argument works too. I've never actually tried defining functions in the class file, but outside of the classdef, but it does seem to work, and crucially the function still have access to the private data which I had thought wouldn't be the case before I ran your example!
e.g. I would do:
'callback',@(h,e) obj.Callback_OK()
with
methods( Access = private )
function Callback_Ok( obj )
close( obj.fig );
end
end
and all the other callbacks also in that private block. But it amounts to the same thing!
Rik
Rik on 7 Oct 2019
@Adam, please feel free to add your style of a programmatic class-based GUI to the answer section.
Stephen23
Stephen23 on 7 Oct 2019
Adam
Adam on 7 Oct 2019
Personally I see the GUI Layout Toolbox as a subsection of Programmetic GUIs, but it is definitely worthy of inclusion. Indeed, I wouldn't go near a programmatic GUI for anything non-trivial without using the GUI Layout Toolbox myself as the thought of having to position all the elements myself would be a nightmare!
I also find, when doing a programmatic UI (since well before App Designer was released), that a class-based design for this works best for me.
At its most basic level even a single class representing the whole UI acts as an easy container to give access to all the components you need without needing to mess about with the standard GUIDE-like methods of structs or appdata. Personally I go a few steps further and create classes for my tabs or panels, with reusable components that I can plug into different GUIs, but that is more advanced and, with the imminent death of javacomponent, is something that has a limited lifetime for me since I make quite heavy use of some java components, laid out using the GUI Layout Toolbox.
So I'm not sure what approach I will move towards for creating future GUIs. App Designer is well short of being usable for me and I haven't yet tried a programmatic GUI using a uifigure myself.
Adam Danz
Adam Danz on 4 Oct 2019
I think drag-n-drop construction of GUIs is a useful tool, especially for beginners, but it comes with limitations and, in the case of GUIDE, occasional bugs, if not used properly. Unlike drag-n-drop methods, building a GUI from the bottom-up requires a greater investment of time during development but the payoffs are
  • more control of the GUI components
  • easier troubleshooting
  • less overhead (I still get flustered when the GUI initialization runs twice during GUIDE GUI startup)
  • a deeper background knowledge of graphical objects and their properties
  • time saved in the long run by avoiding problems that are otherwise difficult or impossible to trace
Even with a beginner's level of Matlab experience, IMO these resources below are enough to get started in making a gui from the bottom-up.
  1. Know the UI options. The user interface can be created on a figure() or a uifigure(). Each have a different set of components that are not compatible with the other and they both have a different appearance.
  2. For figure() GUIs, interactive components are mainly added using uicontrol() and thier properties are listed here. A list of some of the components that can be included in a figure() GUI is here. Most of the time there are useful examples in the documentation how to implement a UI component, set its properties, and write its callback function. To start, the 'units' and 'position' properties will allow you to position the component within the figure.
  3. For uifigure() GUIs, interactive components are added by their individual functions. A list of uifigure() components is here which includes links to the properties of each component.
  4. Understanding callback functions. Many of the UI components have a wide range of callback functions that are invoked by user interaction. Here is a long list of callback options, the action that invokes them, and the components that allow them. This link provides decent examples of how to define a callback function and how to specify its inputs while this link shows callback function examples for each type of UI component.
It all boils down to being familiar with the list of UI components, their properties, and their callback function options. It may sound like a lot to a beginner but most of the properties and callback functions behave the same between components so the level of understand should accelerate after just a few successfully implemented buttons or sliders.
Rik
Rik on 4 Oct 2019
A programmatic GUI is ideal if you need a lot of flexibility and many possibilies for support of old releases. It is less visual when designing, but that can be mitigated by either trial and error in a script, or by using GUIDE to design the initial layout and get the Position right for your objects.
My small guide to avoid GUIDE:
  • Make a figure (with f=figure;) and look into the doc for figure which properties you want to turn off (you probably want to set Menu and Toolbar to 'none')
  • Create buttons and axes and everything you need with functions like uicontrol and axes. Save the handles to each element to fields of a struct (like handles.mybutton=uicontrol(___);)
  • Use those handles in function calls that create graphics objects. Never use gcf and gca in your code, because the user might have clicked on a different figure window, making those call targets incorrect. Most functions allow you to specify a parent object (including, plot, bar, axes and many more). When creating a graphics object, check the documentation to see how you can specify the parent.
  • When you've finished loading all data (and saving it to fields of your handles struct), and creating all the buttons, save your handles struct to the guidata of your figure like this guidata(handles.f,handles);. (You can also use getappdata and setappdata)
  • You can set the Callback property of many objects. If you do, use a function name with an @ in front, or a char array that can be evaluated to valid code. (like @MyFunction or 'disp(''you pushed the button'')')
  • Callback functions will be called with two arguments: the first is a handle to the callback object, the second is eventdata that may contain special information. To get access to your data, just use handles=guidata(gcbo);. You can replace the gcbo function with the name of the first input to your callback function if you prefer.
  • More information about callbacks can be found in multiple places in the doc, for example here.
Rik
Rik on 7 Oct 2019
You do sacrifice compatibility with GNU Octave by using nested functions (although that might not be a concern, I think it is important for it be mentioned).
Stephen23
Stephen23 on 7 Oct 2019