Is it possible to write a GUI from inside a function?
The problem is that the callback of all GUI-functions are evaluated in the global workspace. But functions have their own workspace and can not access variables in the global workspace. Is it possible to make the GUI-functions use the workspace of the function? For example:
function myvar = myfunc() myvar = true; h_fig = figure; % create a useless button uicontrol( h_fig, 'style', 'pushbutton', ... 'string', 'clickme', ... 'callback', 'myvar = false' ); % wait for the button to be pressed while myvar pause( 0.2 ); end close( h_fig ); disp( 'this will never be displayed' ); end
This event-loop will run indefinitely, since the callback will not modify myvar in the function. Instead it will create a new myvar in the global workspace.
There are a number of ways to build a GUI, such as using the App Designer, GUIDE, or creating it programmatically (I’ll illustrate this option below). It’s also important to be aware of the different ways to define callback functions for your GUI components and the options available for sharing data between components.
The approach I’m partial to is using nested functions as callbacks. Here’s a simple GUI as an example:
When you run this code, the counter displayed should increment by one every time you press the button, because the nested function
incrementhas access to the workspace ofmake_useless_buttonand thus can modifyiCounter. Note that the button callback is set to a function handle toincrement, and that this function must accept two arguments by default: a graphics handle for the UI component that triggered the callback, and a structure of associated event data. We ignore them with the~in this case since we aren’t using them.Extending the above approach to your particular problem, you could add your loop and change the callback so it sets your flag variable to false:
The
drawnowis needed here to give the button callback a chance to interrupt the program flow within the loop and modify the value ofkeepLooping.