如何在MATLAB中的函数内创建GUI?

时间:2008-11-07 15:50:24

标签: matlab function user-interface

是否可以从函数内部编写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

3 个答案:

答案 0 :(得分:5)

build a GUI有多种方法,例如使用App Designer,GUIDE或以编程方式创建(我将在下面说明此选项)。了解GUI组件的different ways to define callback functionsoptions 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 handleiCounter,并且此函数默认情况下必须接受两个参数:触发回调的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

的修改之前,您将始终至少延迟0.2秒