How to create a GUI inside a function in MATLAB?

前端 未结 3 1420
陌清茗
陌清茗 2020-12-03 19:26

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

相关标签:
3条回答
  • 2020-12-03 19:47

    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:

    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

    0 讨论(0)
  • 2020-12-03 19:48

    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.

    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'

    0 讨论(0)
  • 2020-12-03 19:53

    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:

    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 increment has access to the workspace of make_useless_button and thus can modify iCounter. Note that the button callback is set to a function handle to 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.

    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:

    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 drawnow is needed here to give the button callback a chance to interrupt the program flow within the loop and modify the value of keepLooping.

    0 讨论(0)
提交回复
热议问题