是否可以从函数内部编写GUI?
问题是所有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
此事件循环将无限期运行,因为回调不会修改函数中的myvar
。相反,它将在全局工作区中创建一个新的myvar
。
答案 0 :(得分:5)
build a GUI有多种方法,例如使用App Designer,GUIDE或以编程方式创建(我将在下面说明此选项)。了解GUI组件的different ways to define callback functions和options available for sharing data between components也很重要。
我偏爱的方法是使用nested functions作为回调。这是一个简单的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
当您运行此代码时,每次按下按钮时显示的计数器应递增1,因为嵌套函数increment
可以访问make_useless_button
的工作区,因此可以修改{{1 }}。请注意,按钮回调设置为function handle到iCounter
,并且此函数默认情况下必须接受两个参数:触发回调的UI组件的图形句柄,以及关联事件的结构数据。在这种情况下我们ignore them with the ~
,因为我们没有使用它们。
将上述方法扩展到您的特定问题,您可以添加循环并更改回调,以便将flag变量设置为false:
increment
此处需要drawnow
以使按钮回调有机会中断循环中的程序流并修改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
的值。
答案 1 :(得分:1)
如果回调是在一个单独的函数而不是内联函数中,您可以在函数中声明一个变量global,在GUI代码中声明全局变量。我在一个用于制作快速菜单系统的小骨架GUI中完成了这个。
在上面的代码中,您可以将global关键字添加到初始声明中,也可以添加到内联回调中,即'global myvar = false'
答案 2 :(得分:1)
我找到了问题的解决方案。回调函数必须修改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
请注意,由于while循环只会在运行时更新fig_handles,因此在循环捕获fig_handles.continue_loop