如何在 MATLAB 的函数内创建 GUI?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/272511/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create a GUI inside a function in MATLAB?
提问by bastibe
Is it possible to write a GUI from inside a function?
是否可以从函数内部编写 GUI?
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:
问题是所有 GUI 函数的回调都在全局工作区中进行评估。但是函数有自己的工作空间,不能访问全局工作空间中的变量。是否可以使 GUI 功能使用该功能的工作区?例如:
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 myvarin the function. Instead it will create a new myvarin the global workspace.
这个事件循环将无限期运行,因为回调不会myvar在函数中修改。相反,它将myvar在全局工作区中创建一个新的。
采纳答案by gnovice
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 functionsfor your GUI components and the options available for sharing data between components.
有多种构建 GUI 的方法,例如使用 App Designer、GUIDE 或以编程方式创建它(我将在下面说明此选项)。了解为 GUI 组件定义回调函数的不同方式以及可用于在组件之间共享数据的选项也很重要。
The approach I'm partial to is using nested functionsas callbacks. Here's a simple GUI as an example:
我偏爱的方法是使用嵌套函数作为回调。下面以一个简单的 GUI 为例:
function make_useless_button()
% Initialize variables and graphics:
iCounter = 0;
hFigure = figure;
hButton = uicontrol('Style', 'pushbutton', 'Parent', hFigure, ...
'String', 'Blah', 'Callback', @increment);
% Nested callback function:
function increment(~, ~)
iCounter = iCounter+1;
disp(iCounter);
end
end
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 of make_useless_buttonand thus can modify iCounter. Note that the button callback is set to a function handleto increment, 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.
运行此代码时,每次按下按钮时显示的计数器都应增加 1,因为嵌套函数increment可以访问 的工作区,make_useless_button因此可以修改iCounter. 请注意,按钮回调被设置为一个函数句柄来increment,那这个函数必须接受两个参数默认为:用于触发回调的UI组件的图形处理,以及相关的事件数据的结构。我们忽略了他们与~,因为我们不使用它们在这种情况下。
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:
将上述方法扩展到您的特定问题,您可以添加循环并更改回调,以便将您的标志变量设置为 false:
function make_stop_button()
% Initialize variables and graphics:
keepLooping = true;
hFigure = figure;
hButton = uicontrol('Style', 'pushbutton', 'Parent', hFigure, ...
'String', 'Stop', 'Callback', @stop_fcn);
% Keep looping until the button is pressed:
while keepLooping,
drawnow;
end
% Delete the figure:
delete(hFigure);
% Nested callback function:
function stop_fcn(~, ~)
keepLooping = false;
end
end
The drawnowis needed here to give the button callback a chance to interrupt the program flow within the loop and modify the value of keepLooping.
在drawnow这里需要给按键回调几率打断循环内的程序流和修改的值keepLooping。
回答by Ian Hopkinson
You can declare a variable global in your function and global in the GUI code, certainly if the callback is in a separate function rather than inline. I've done this in a little skeleton GUI I use to make quick menu system.
您可以在函数中声明一个 global 变量,并在 GUI 代码中声明一个 global 变量,当然如果回调位于单独的函数中而不是内联函数中。我已经在一个用于制作快速菜单系统的小骨架 GUI 中完成了这项工作。
In your code above you may be able to add the global keyword to your initial declaration and also to your inline callback i.e. 'global myvar = false'
在上面的代码中,您可以将 global 关键字添加到初始声明以及内联回调中,即“global myvar = false”
回答by bastibe
I found a solution to the problem. The callback-function has to modify the handle-structure of the GUI. This structure can be accessed both from within the callback and from the function without introducing new variables to the global workspace:
我找到了解决问题的方法。回调函数必须修改 GUI 的句柄结构。可以从回调和函数中访问此结构,而无需向全局工作区引入新变量:
function myfunc()
h_fig = figure;
% add continue_loop to the GUI-handles structure
fig_handles = guihandles( h_fig );
fig_handles.continue_loop = true;
guidata( h_fig, fig_handles );
% create a useless button
uicontrol( h_fig, 'style', 'pushbutton', ...
'string', 'clickme', ...
'callback', @gui_callback );
% wait for the button to be pressed
while fig_handles.continue_loop
fig_handles = guidata( h_fig ); % update handles
pause( 0.2 );
end
close( h_fig );
disp( 'callback ran successfully' );
end
% The arguments are the Matlab-defaults for GUI-callbacks.
function gui_callback( hObject, eventdata, handles )
% modify and save handles-Structure
handles.continue_loop = false;
guidata( hObject, handles );
end
note that since the while-loop will only update fig_handles when it is run, you will always have at least 0.2 seconds delay until the loop catches the modification of fig_handles.continue_loop
请注意,由于 while 循环只会在运行时更新 fig_handles,因此在循环捕获到fig_handles.continue_loop

