Skip to Main Content Skip to Search
Product Documentation

Making Multiple GUIs Work Together

Data-Sharing Techniques

Several of the techniques described in Examples of Sharing Data Among a GUI's Callbacks for sharing data within a GUI can also share data among several GUIs. You can use GUI data, application data, and UserData property to communicate between GUIs as long as the handles to objects in the first GUI are made available to other GUIs. This section provides two examples that illustrate these techniques:

Example — Manipulating a Modal Dialog Box for User Input

This example illustrates how to do the common tasks involved in making multiple GUIs work together. It explains how to position a second GUI relative to the main GUI and demonstrates how data is passed to a modal dialog box invoked from a GUIDE GUI. The dialog box displays text data in an edit field. Changes that you make to the edit field are passed back to the main GUI. The main GUI uses this data in various ways. You can update the appearance of one of the components of the main GUI by changing the data in the modal dialog box.

The main GUI, called changeme_main, contains one button and a static text field giving instructions. When you click the button, the modal changeme_dialog dialog box opens and the button's current string appears in an editable text field that you can then change.

If you click OK, the value of the text field is returned to the main GUI, which sets the string property of the button to the value you entered. The main GUI and its modal dialog box are shown in the following figure.

View and Run the changeme GUI

If you are reading this in the MATLAB Help browser, you can access the example FIG-files and code files by clicking the following links. If you are reading this on the Web or in PDF form, you should go to the corresponding section in the MATLAB Help Browser to use the links.

If you intend to modify the layout or code of this GUI example, you should first save copies of its code files and FIG-files to your current folder (You need write access to your current folder to do this.) Follow these steps to copy the example files to your current folder and then to open them:

  1. Click here to copy the files to your current folder.

  2. Type the commands guide changeme_main; guide changeme_dialog or click here to open the two GUIs in GUIDE.

  3. Type the commands edit changeme_main.m; edit changeme_dialog.m or click here to open the GUI code files in the Editor.

You can view the properties of any component by double-clicking it in the Layout Editor to open the Property Inspector for it. You can modify either the figure, the code, or both. Then you can save the GUI in your current folder using File > Save As from GUIDE. This saves both the GUI and its code file. If you save one of the GUIs in this way, you need to save the other one as well.

If you just want to run the GUI or inspect it in GUIDE, follow these steps:

  1. Click here to add the example files to the MATLAB path (only for the current session).

  2. Click here to run the changeme_main GUI.

  3. Click here to display the GUI in the GUIDE Layout Editor (read-only).

  4. Click here to display the GUI code file in the MATLAB Editor (read-only).

Do not change the file name of either GUI when using Save As. Because the changeme_main code calls the changeme_dialog function, modifying that file name would make the GUI inoperable.

Invoking the Text Change Dialog Box

When the user clicks the Change Me button, the Text Change dialog box opens. Invoke this dialog box by calling its main function with a property/value pair:

function buttonChangeMe_Callback(hObject,eventdata, handles)

% Call the dialog to change button name giving this figure's handle
changeme_dialog('changeme_main', handles.figure);

The dialog box uses the handle to access the main GUI's data. If the main GUI's data is missing, the dialog box displays an error in the Command Window that describes proper usage and then exits.

Managing the Text Change Dialog

  1. In the Property Inspector for the Text Change dialog box's figure, set the WindowStyle property to 'Modal'. This ensures that when the dialog box is active the user cannot interact with other figures.

  2. Call uiwait in the OpeningFcn of the dialog box to put off calling the output function until uiresume is called. This keeps the invocation call of the GUI from returning until that time:

    function changeme_dialog_OpeningFcn(hObject,eventdata,handles,varargin)
    .
    .
    .
    uiwait(hObject);
    .
    .
    .
    
  3. Invoke uiresume within CloseRequestFcn for the figure, the Cancel button, and the OK button. Every callback in which the GUI needs to close should call uiresume:

    function buttonCancel_Callback(hObject,eventdata,handles)
    
    uiresume(handles.figure);
    
    
    function figure_CloseRequestFcn(hObject,eventdata,handles)
    
    uiresume(hObject);
    
    
    function buttonOK_Callback(hObject,eventdata,handles)
    .
    .
    .
    uiresume(handles.figure);

Protecting and Positioning the Text Change Dialog

  1. The user opens the Text Change dialog box by triggereing the main GUI's buttonChangeMe_Callback callback, which supplies the main GUI's figure handle as a property called changeme_main.

  2. The OpeningFcn for the dialog box validates the input by searching and indexing into the varagin cell array. If 'changeme_main' and a handle are found as successive arguments, it calls uiwait. This ensures that the dialog GUI can exit without waiting for OutputFcn to close the figure. If it does not find the property or finds an invalid value, the modal dialog box displays an error and exits.

    function changeme_dialog_OpeningFcn(hObject, ...
             eventdata, handles, varargin)
    
    % Is the changeme_main gui's handle is passed in varargin?
    % if the name 'changeme_main' is found, and the next argument
    % varargin{mainGuiInput+1} is a handle, assume we can open it.
    
    dontOpen = false;
    mainGuiInput = find(strcmp(varargin, 'changeme_main'));
    if (isempty(mainGuiInput)) 
      || (length(varargin) <= mainGuiInput) 
      || (~ishandle(varargin{mainGuiInput+1}))
        dontOpen = true;
    else
    .
    .
    .
    end
    .
    .
    .
    if dontOpen
       disp('-----------------------------------------------------');
       disp('Improper input arguments. Pass a property value pair') 
       disp('whose name is "changeme_main" and value is the handle')
       disp('to the changeme_main figure.');
       disp('eg:');
       disp('   x = changeme_main()');
       disp('   changeme_dialog('changeme_main', x)');
       disp('-----------------------------------------------------');
    else
       uiwait(hObject);
    end
  3. The changeme_dialog_OpeningFcn centers the Text Change dialog box over the main GUI, using the passed-in handle to that figure. So, if the main figure is moved and the dialog box is invoked, it opens in the same relative position instead of always in a fixed location.

    function changeme_dialog_OpeningFcn(hObject, ...
             eventdata, handles, varargin)
    .
    .
    .  
    mainGuiInput = find(strcmp(varargin, 'changeme_main'));
    .
    .
    .
    handles.changeMeMain = varargin{mainGuiInput+1};
    .
    .
    .
    % Position to be relative to parent:
    parentPosition = getpixelposition(handles.changeMeMain);
    currentPosition = get(hObject, 'Position');  
    % Sets the position to be directly centered on the main figure
    newX = parentPosition(1) + (parentPosition(3)/2 ...
           - currentPosition(3)/2);
    newY = parentPosition(2) + (parentPosition(4)/2 ...
           - currentPosition(4)/2);
    newW = currentPosition(3);
    newH = currentPosition(4);
    
    set(hObject, 'Position', [newX, newY, newW, newH]);
    .
    .
    .

Initializing Text in the Text Change Dialog Box

  1. To initialize the Text Change dialog box text to the Change Me button's current text, get the main GUI's handles structure from its handle, passed to the modal dialog box:

    function changeme_dialog_OpeningFcn(hObject, ...
             eventdata, handles, varargin)
    
    mainGuiInput = find(strcmp(varargin, 'changeme_main'));
    .
    .
    .
    handles.changeMeMain = varargin{mainGuiInput+1};
  2. Get the Change Me button's String property and set the String property of the edit box to that value in the dialog box OpeningFcn.

        % Obtain handles using GUIDATA with the caller's handle 
        mainHandles = guidata(handles.changeMeMain);
        % Set the edit text to the String of the main GUI's button
        set(handles.editChangeMe, 'String', ...
            get(mainHandles.buttonChangeMe, 'String'));
    .
    .
    .

Canceling the Text Change Dialog Box

Call uiresume to close the modal dialog box if the user clicks Cancel or closes the window. Do not modify the main GUI to close the modal dialog box.

function buttonCancel_Callback(hObject, ...
         eventdata, handles)
uiresume(handles.figure);
 
function figure_CloseRequestFcn(hObject, ...
         eventdata, handles)
uiresume(hObject);

Applying the Text Change

Use the reference to the main GUI in the handles structure saved by OpeningFcn in the modal dialog box to apply the text change. The user clicks OK to apply the text change. This sets the Change Me button label in the main GUI to the value entered in the text field of the modal dialog box.

function buttonOK_Callback(hObject, ...
         eventdata, handles)
text = get(handles.editChangeMe, 'String');
main = handles.changeMeMain;
mainHandles = guidata(main);
changeMeButton = mainHandles.buttonChangeMe;
set(changeMeButton, 'String', text);
uiresume(handles.figure);

Closing the Main GUI

When the user closes the changeme_dialog GUI, the changeme_main GUI is in a waiting state. The user can either click the push button to change the name again or close the GUI by clicking the X close box. When the user closes the GUI, its OutputFcn returns the push button's current label (its String property) before deleting the GUI figure:

function varargout = changeme_dialog_Dialog_OutputFcn...
			             (hObject, eventdata, handles)
% Get pushbutton string from handles structure and output it
varargout{1} = get(handles.buttonChangeMe,'String');
% Now destroy yourself
delete(hObject);

You also need a CloseRequestFcn. If you do not specify one, the GUI cannot output data because the default CloseRequestFcn, the MATLAB function closreq, immediately deletes the figure before any OutputFcn can be called. This figure_CloseRequestFcn does that, but only if the GUI is not in a wait state; if it is, it calls uiresume and returns, enabling the OutputFcn to be called:

function figure_CloseRequestFcn(hObject,eventdata,handles)
% hObject    handle to figure (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Check appdata flag to see if the main GUI is in a wait state
if getappdata(handles.figure,'waiting')
    % The GUI is still in UIWAIT, so call UIRESUME and return
    uiresume(hObject);
    setappdata(handles.figure,'waiting',0)
else
    % The GUI is no longer waiting, so destroy it now.
    delete(hObject);
end

Example — Individual GUIDE GUIs Cooperating as Icon Manipulation Tools

This example demonstrates how three GUIs in GUIDE work together when invoked from the main GUI. The tools are listed and illustrated below:

These GUIs share data and expose functionality to one another using several different techniques:

View and Run the Three Icon Manipulation GUIs

If you are reading this in the MATLAB Help browser, you can access the example FIG-files and code files by clicking the following links. If you are reading this on the Web or in PDF form, you should go to the corresponding section in the MATLAB Help Browser to use the links.

If you intend to modify the layout or code of this GUI example, you should first save copies of its code files and FIG-files to your current folder (You need write access to your current folder to do this.) Take the following steps to copy the example files to your current folder and open them:

  1. Click here to copy the files to your current folder.

  2. Type the commands guide guide_iconeditor; guide guide_toolpalette; guide guide_colorpalette or click here to open the two GUIs in GUIDE.

  3. Type the commands edit guide_iconeditor.m; edit guide_toolpalette.m; edit guide_colorpalette.m or click here to open the GUI code files in the Editor.

You can view the properties of any component by double-clicking it in the Layout Editor to open the Property Inspector for it. You can modify either the figure, the code, or both. Then you can save the GUI in your current folder using File > Save as from GUIDE. This saves both files, allowing you to rename them if you choose.

If you just want to run the GUI or inspect it in GUIDE, follow these steps:

  1. Click here to add the example files to the MATLAB path (only for the current session).

  2. Click here to run the guide_iconeditor GUI.

  3. Click here to display the GUI in the GUIDE Layout Editor (read-only).

  4. Click here to display the GUI code file in the MATLAB Editor (read-only).

The behavior of the Icon Editor application is described in this sequence:

Icon Editor Implementation

The Icon Editor application uses three code files and three FIG-files that are fully implemented in GUIDE. You can modify and enhance them in the GUIDE environment if you choose. The files are:

The code files contain the following function signatures and outputs (if any):

Opening the Icon Editor and the Tool and Color Palettes

When you open the Icon Editor, the Tool Palette and Color Palette automatically start up. The palettes are children of the Icon Editor and communicate as described here:

The Icon Editor is passed into the Tool Palette, and Color Palette as a property/value (p/v) pair that allows the Tool and Color Palettes to make calls back into the Icon Editor. The output value from calling both of the palettes is the handle to their GUI figures. These figure handles are saved into the handles structure of Icon Editor:

% in Icon Editor
function guide_Icon Editor_OpeningFcn(hObject,eventdata,handles,varargin)
.
.
.
handles.colorPalette = guide_colorpalette('iconEditor',hObject);
handles.toolPalette  =  guide_toolpalette('iconEditor',hObject);
.
.
.
% Update handles structure
guidata(hObject, handles);

The Color Palette needs to remember the Icon Editor for later:

% in colorPalette
function guide_colorpalette_OpeningFcn(hObject,eventdata,handles,varargin)
handles.output = hObject;
.
.
.
handles.iconEditor = [];

iconEditorInput = find(strcmp(varargin, 'iconEditor'));
if ~isempty(iconEditorInput)
   handles.iconEditor = varargin{iconEditorInput+1};
end
.
.
.
% Update handles structure
guidata(hObject, handles);

The Tool Palette also needs to remember the Icon Editor:

% in toolPalette
function guide_toolpalette_OpeningFcn(hObject, ...
         eventdata, handles, varargin)
handles.output = hObject;
.
.
.
handles.iconEditor = [];

iconEditorInput = find(strcmp(varargin, 'iconEditor'));
if ~isempty(iconEditorInput)
   handles.iconEditor = varargin{iconEditorInput+1};
end
.
.
.
% Update handles structure
guidata(hObject, handles);

Setting the Initial Color on the Color Palette

After you create all three GUIs, you need to set the initial color. When you invoke the Color Palette from the Icon Editor, the Color Palette passes a function handle that tells the Icon Editor how to set the initial color. This function handle is stored in its handles structure. You can retrieve the handles structure from the figure to which the Color Palette outputs the handle:

% in colorPalette
function guide_colorpalette_OpeningFcn(hObject, ...
         eventdata, handles, varargin)
handles.output = hObject;
.
.
.
% Set the initial palette color to black
handles.mSelectedColor = [0 0 0];

% Publish the function setSelectedColor
handles.setColor = @setSelectedColor;
.
.
.
% Update handles structure
guidata(hObject, handles);


% in colorPalette
function setSelectedColor(hObject, color)
handles = guidata(hObject);
.
.
.
handles.mSelectedColor =color;
.
.
.
guidata(hObject, handles);

Call the publicized function from the Icon Editor, setting the initial color to 'red':

% in Icon Editor
function guide_iconeditor_OpeningFcn(hObject, ...
         eventdata, handles, varargin)
.
.
.
handles.colorPalette = guide_colorpalette('iconEditor', hObject);
.
.
.
colorPalette = handles.colorPalette;
colorPaletteHandles = guidata(colorPalette);
colorPaletteHandles.setColor(colorPalette, [1 0 0]);
.
.
.
% Update handles structure
guidata(hObject, handles);

Accessing the Color Palette's Current Color from the Icon Editor

The Color Palette initializes the current color data:

%in colorPalette
function guide_colorpalette_OpeningFcn(hObject, ...
         eventdata, handles, varargin)
handles.output = hObject;
.
.
.
handles.mSelectedColor = [0 0 0];
.
.
.
% Update handles structure
guidata(hObject, handles);

The Icon Editor retrieves the initial color from the Color Palette's GUI data via its handles structure:

% in Icon Editor
function color = getColor(hObject)
handles = guidata(hObject);
colorPalette = handles.colorPalette;
colorPaletteHandles = guidata(colorPalette);
color = colorPaletteHandles.mSelectedColor;

Using UserData Property to Share Data

You can use the UserData property of components in your GUIDE GUI to share data. When you click the mouse in the icon editing area, you select a tool. You can use every tool in the Tool Palette to modify the icon you are editing by altering the tool's CData. The GUI uses the UserData property of each tool to record the function that you call when a tool is selected and applied to the icon-editing area. Each tool alters different aspects of the icon data. Here is an example of how the pencil tool works.

In the CreateFcn for the pencil tool, add the user data that points to the function for the pencil tool:

% in toolPalette
function toolPencil_CreateFcn(hObject, eventdata, handles)
set(hObject,'UserData', struct('Callback', @pencilToolCallback));

The Tool Palette tracks the currently selected tool in its handles structure's mCurrentTool field. You can get this structure from other GUIs after you create the handles structure of the Tool Palette. Set the currently selected tool by calling guidata after you click a button in the Tool Palette:

% in toolPalette
function toolPalette_SelectionChangeFcn(hObject, ...
        eventdata, handles)
handles.mCurrentTool = hObject;
guidata(hObject, handles);

When you select the pencil tool and click in the icon-editing area, the Icon Editor calls the pencil tool function:

% in iconEditor
function iconEditor_WindowButtonDownFcn(hObject,...
         eventdata, handles)
toolPalette = handles.toolPalette;
toolPaletteHandles = guidata(toolPalette);
	.
	.
	.
userData = get(toolPaletteHandles.mCurrentTool, 'UserData');
handles.mIconCData = userData.Callback(toolPaletteHandles, ...
        toolPaletteHandles.mCurrentTool, handles.mIconCData, ...);

The following code shows how the pixel value in the icon-editing area under the mouse click (the Tool icon's CData) changes to the color currently selected in the Color Palette:

% in toolPalette
function cdata = pencilToolCallback(handles, toolstruct, cdata,...)
iconEditor = handles.iconEditor;
iconEditorHandles = guidata(iconEditor);
x = ...
y = ...
% update color of the selected block
color = iconEditorHandles.getColor(iconEditor);
cdata(y, x,:) = color;

Displaying the Current Tool's Cursor

You can have the cursor display the current tools pointer icon when the mouse is in the editing area and the default arrow displays outside the editing area. To do this you must identify the selected tool through the Tool Palette's handles structure:

% in Icon Editor
function iconEditor_WindowButtonMotionFcn(hObject, ...
        eventdata, handles)
.
.
.
rows = size(handles.mIconCData,1);
cols = size(handles.mIconCData,2);
pt = get(handles.icon,'currentpoint');
overicon = (pt(1,1)>=0 && pt(1,1)<=rows) && ...
           (pt(1,2)>=0 && pt(1,2)<=cols);
.
.
.
if ~overicon
    set(hObject,'pointer','arrow');        
else
    toolPalette = handles.toolPalette;
    toolPaletteHandles = guidata(toolPalette);
    tool = toolPaletteHandles.mCurrentTool;
    cdata = round(mean(get(tool, 'cdata'),3))+1;
    if ~isempty(cdata)
        set(hObject,'pointer','custom','PointerShapeCData', ...
        cdata(1:16, 1:16),'PointerShapeHotSpot',[16 1]);        
    end
end
.
.
.

Closing All Windows When Complete

When the Icon Editor opens, it opens the Color Palette and Tool Palette, saving their handles and other data in the handles structure. The last thing the Icon Editor OpeningFcn does is to call uiwait to defer output until the GUI is complete. When you need to close the windows, neither the Color Palette nor Tool Palette close independently of the Icon Editor because there is a complicated close sequence involved. You can close all windows using one of these methods:

You cannot close the Color Palette and Tool Palette windows by directly clicking their close button (X).

In the next example, you set the output of Icon Editor to be the CData of the icon. The opening function for Icon Editor, with uiwait, contains this code:

% in Icon Editor
function guide_iconeditor_OpeningFcn(hObject, eventdata, ...
        handles, varargin)

.
.
.
handles.colorPalette = guide_colorpalette();
handles.toolPalette = guide_toolpalette('iconEditor', hObject);
.
.
. 
% Update handles structure
guidata(hObject, handles);
uiwait(hObject);

As a result, you must call uiresume on each exit path:

% in Icon Editor
function buttonOK_Callback(hObject, eventdata, handles)
uiresume(handles.figure);

function buttonCancel_Callback(hObject, eventdata, handles)
% Make sure the return data will be empty if we cancelled
handles.mIconCData =[];
guidata(handles.figure, handles);
uiresume(handles.figure);

function Icon Editor_CloseRequestFcn(hObject, eventdata, handles)
uiresume(hObject);

To ensure that the Color Palette is not closed any other way, override its closerequestfcn to take no action:

% in colorPalette
function figure_CloseRequestFcn(hObject, eventdata, handles)
% Don't close this figure. It must be deleted from Icon Editor

Do the same for the Tool Palette:

% in toolPalette
function figure_CloseRequestFcn(hObject, eventdata, handles)
% Don't close this figure. It must be deleted from Icon Editor

Finally, in the output function, delete all three GUIs:

% in Icon Editor
function varargout = guide_iconeditor_OutputFcn(hObject, ...
        eventdata, handles)
% Return the cdata of the icon. If cancelled, this will be empty
varargout{1} = handles.mIconCData;
delete(handles.toolPalette);
delete(handles.colorPalette);
delete(hObject);
  


Recommended Products

Includes the most popular MATLAB recorded presentations with Q&A sessions led by MATLAB experts.

 © 1984-2012- The MathWorks, Inc.    -   Site Help   -   Patents   -   Trademarks   -   Privacy Policy   -   Preventing Piracy   -   RSS