Stuart’s MATLAB Videos

Watch and Learn

MATLAB Basics: GUIs without GUIDE 10

Posted by Doug Hull,

GUIDE is the standard way of creating GUIs in MATLAB, but sometimes it is better to make the GUI programmatically. This often happens when you want to easily create and destroy buttons and other widgets during the course of the GUI’s use. Handwritten code is often more compact and gives you more control over your GUI. This eight and a half minute video shows you how to make a GUI without using GUIDE. This GUI will allow one button to create a second button. The second button will delete itself when clicked. This shows how dynamic GUIs can be built.
Other videos have been gathered here: https://blogs.mathworks.com/pick/category/video/ Other MATLAB Basics posts have been gathered here: https://blogs.mathworks.com/pick/category/matlab-basics/

10 CommentsOldest to Newest

Markus replied on : 1 of 10
Hi Doug! Nice video. Maybe you should have mentioned that the contents of h in the callback is static. Adding the field h.buttonTwo in function addButton does not change the contents of h as saved in the callback of buttonOne. Looking at the line "h = rmfield(h, 'buttonTwo');", which is not necessary here, one might think that h is somehow a global variable. When programming GUIs, I often save data like other handles in the "UserData" field of the figure. In the callback of your example, you could get the handles using the "Parent" property of the buttons. What do you think about that? Regards Markus
Ryan Gray replied on : 2 of 10
I'm surprised you didn't use nested functions for the callbacks to go with earlier hints about GUIs - or maybe that was Loren's blog... function simpleGuiNested h.fig = figure('position', [800 30 210 60]); h.buttonOne = uicontrol('style', 'pushbutton',... 'position',[10 10 100 40], ... 'string' , 'Add button', ... 'callback', {@addButton}); function addButton(hObject, eventdata) h.buttonTwo = uicontrol('style', 'pushbutton', ... 'position',[100 10 100 40], ... 'string' , 'Remove button', ... 'callback', {@removeButton}); set(h.buttonOne, 'enable', 'off'); end function removeButton(hObject, eventdata) delete(h.buttonTwo) h = rmfield(h, 'buttonTwo'); set(h.buttonOne, 'enable', 'on') end end
Ryan Gray replied on : 3 of 10
By the way, the iPod .m4v file is only playing audio for me. "Parsing code for better understanding" is also audio-only.
Markus replied on : 4 of 10
Aaargh, I am glad Doug does NOT promote nested functions!! The concept of variable scope gets very complicated with nested functions. I really don't want to be the one who has to debug code with nested functions. There is always a good way without using nested functions. Markus
Ryan Gray replied on : 5 of 10
Sorry that the indentation of my code got eaten, making it not as readable. Note the trick of creating the control first, then setting the callback because the uicontrol gets passed the structure of handles is no longer needed. You also don't then really need to store everything in a structure for convenience of passing the handles around since they do not need to be. It seems to me that perhaps a good convention might be to decorate the names of the nested functions with the name of the function they are nested in, for example: simpleGuiNested_ addButton and simpleGuiNested_ removeButton. I don't think the variable scope is what gets complicated with nested functions; if anything, it's the variable persistence. When you take the handles to the nested functions, you are causing the enclosing scope they depend on to not be destroyed automatically. So, when the main function ends, its variable space persists until the references are released, which happens here when the window is destroyed, which destroys the callback handles. That's the part I find hard about nested functions. I guess it helps if you've programmed Pascal, which has nested functions. One technique I use them for that I used to use in Pascal was to cleanup a procedure by just throwing a section of code into a nested function. You don't have to go through and figure out what variables you need to pass and return since the scope is the same. The bonus is that temporary variables that apply only to that segment can be local to the nested function and not persist in the rest of the larger procedure where they might cause trouble. This makes creating subroutines almost trivial, so that you will tend to do it rather than think about how you should and moan that it will take too much effort to figure out all the call parameters, pass them in and also declare them in the function definition.
Doug replied on : 6 of 10
Markus, Excellent catch with the scoping and the static nature of h. Scoping can be tricky and I made a mistake! You are completely correct. E-mail me your snail mail address and I will send you some MATLAB goodies for catching this. While it is an unneeded step, it does not harm anything, so I am not going to reshoot the video. Thanks for the catch. Doug
Doug replied on : 7 of 10
Ryan, Indeed, it is Loren that has covered Nested Functions more: https://blogs.mathworks.com/loren/2006/02/08/use-nested-functions-to-memoize-costly-functions/ I have an upcoming post with nested functions, but Loren is very good with them. Doug
Doug replied on : 8 of 10
Ryan, I just remade the video and posted it. It seems to be working now. Not sure what happened. Thanks, Doug
Lauren replied on : 9 of 10
I have a question regarding the first comment by Markus--I'm new to guis and subfunctions, and therefore having "static variables." If I want to return a variable from a callback, do I have to use a global variable? Is there any other way? I'm currently using guidata, but this is adding a lot of lines to my code having to repeatedly "get" and "set" the data. More generally, what is the result of using: h = callback(arguments) if h can't be changed by the callback anyway? Thanks much for the help! cheers, Lauren
Doug replied on : 10 of 10
Lauren, What would it mean to have a return value from a callback? What workspace would that variable go back to, and where in the program would you be? I prefer GETAPPDATA, SETAPPDATA, as shown in this video: https://blogs.mathworks.com/pick/2005/10/03/guide-video-part-two/ Doug