5

是否可以从函数内部编写 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在全局工作区中创建一个新的。

4

3 回答 3

5

构建 GUI有多种方法,例如使用 App Designer、GUIDE 或以编程方式创建它(我将在下面说明此选项)。了解为您的 GUI 组件定义回调函数的不同方法以及可用于在组件之间共享数据的选项也很重要。

我偏爱的方法是使用嵌套函数作为回调。以下是一个简单的 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

当您运行此代码时,每次按下按钮时显示的计数器应增加一,因为嵌套函数可以increment访问. 请注意,按钮回调设置为 的函数句柄,并且此函数默认情况下必须接受两个参数:触发回调的 UI 组件的图形句柄和关联事件数据的结构。在这种情况下,我们忽略它们,因为我们没有使用它们。make_useless_buttoniCounterincrement~

将上述方法扩展到您的特定问题,您可以添加循环并更改回调,以便将标志变量设置为 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

这里drawnow需要 给按钮回调一个机会来中断循环内的程序流程并修改keepLooping.

于 2009-01-08T18:39:03.643 回答
1

您可以在函数中声明一个全局变量,在 GUI 代码中声明一个全局变量,当然,如果回调在单独的函数中而不是内联函数中。我已经在一个用来制作快速菜单系统的小骨架 GUI 中完成了这项工作。

在上面的代码中,您可以将 global 关键字添加到初始声明以及内联回调中,即“global myvar = false”

于 2008-11-07T16:12:38.513 回答
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

于 2008-11-10T13:07:57.620 回答