MATLAB: Menu-Based GUI through multiple functions (Error while evaluating UIControl Callback & Error while evaluating UIControl Callback)

guimenuuicontrol

ORIGINAL POST: I'm trying to create a menu-driven GUI that relies on multiple functions. The first function opens the figure, then you click on menus or buttons to open the next function and load the new material onto the page. When trying to call my infopage function inside my setup function through a callback function, I get this error: "Error while evaluating UIControl Callback". The error occurs whether I run the infopage function from clicking in the menu or from clicking the button on the screen. When the button is clicked, nothing on the figure changes (that is, none of the objects I set up in the infopage function show on the figure window).
Here is my setup function:
function setup
% This function initiates the entire project
% and sets us up on the title page
page = 1;
fh = figure('Visible','off',...
'Units','Normalized',...
'Position',[0 0 1 1],...
'MenuBar','None');
ax = axes('Units','Normalized',...
'Position',[0 0 1 1]);
flagbg = imread('https://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Flag_of_the_United_States.svg/1280px-Flag_of_the_United_States.svg.png');
titleh = uicontrol('Style','Text',...
'Units','Normalized',...
'Position',[.3 .3 .4 .4],...
'FontName','ColonnaMT',...
'FontSize',60,...
'String','The United States of America');
subtitleh = uicontrol('Style','Text',...
'Units','Normalized',...
'Position',[.3 .3 .4 .2],...
'FontName','Garamond',...
'FontSize',20,...
'String','An Interactive Learning Tool');
buttonh = uicontrol('Style','pushbutton',...
'Units','Normalized',...
'Position',[.4 .4 .2 .05],...
'FontName','Ariel',...
'FontSize',20,...
'String','Click to begin...',...
'Callback',@infopage);
menulabel1 = uimenu('Label','Menu');
uimenu(menulabel1,'Label','Main Menu','Callback',@titlepage);
uimenu(menulabel1,'Label','Info','Callback',@infopage);
uimenu(menulabel1,'Label','Assess','Callback','disp(''save'')');
uimenu(menulabel1,'Label','Compare','Callback','disp(''save'')');
uimenu(menulabel1,'Label','Help','Callback','disp(''save'')');
uimenu(menulabel1,'Label','Quit','Callback','close all',...
'Separator','on');
menulabel2 = uimenu('Label','Info');
uimenu(menulabel2,'Label','State Geography','Callback','disp(''figure'')');
uimenu(menulabel2,'Label','Flag Recognition','Callback','disp(''save'')');
menulabel3 = uimenu('Label','Assess');
uimenu(menulabel3,'Label','State Geography','Callback','disp(''figure'')');
uimenu(menulabel3,'Label','Flag Recognition','Callback','disp(''save'')');
menulabel4 = uimenu('Label','Compare');
uimenu(menulabel4,'Label','New Figure','Callback','disp(''figure'')');
uimenu(menulabel4,'Label','Save','Callback','disp(''save'')');
menulabel5 = uimenu('Label','Help');
uimenu(menulabel5,'Label','New Figure','Callback','disp(''figure'')');
uimenu(menulabel5,'Label','Save','Callback','disp(''save'')');
menulabel6 = uimenu('Label','Credits');
uimenu(menulabel6,'Label','%');
uimenu(menulabel6,'Label','%');
set(ax,'HandleVisibility','off',...
'Visible','off');
set(fh,'Visible','on')
function titlepage(~,~)
close(fh)
setup
end
function infopage(~,~)
infopage;
end
end
Here is my infopage function:
function infopage
StateStruct = loaderfn;
page = 3;
f = figure('Visible','off',...
'Units','Normalized',...
'Position',[0 0 1 1]);
directions = uicontrol('Style','text',...
'Units','Normalized',...
'Position',[0.12 .8 .25 .1],...
'FontSize',33,...
'FontName','Garamond',...
'String','What state do you want to learn about?');
stateselectionh = uicontrol('Style','popup',...
'Units','Normalized',...
'Position',[0.18 0.65 0.13 0.1],...
'FontSize',17,...
'FontName','Garamond',...
'String',{StateStruct.Name},...
'Callback',@callbackfn);
set(f,'Visible','on');
%Set up the callback function to display selected state's data
function callbackfn(source,~)
val = source.Value;
% Set up the state name display
statename = sprintf('%s (%s)',StateStruct(val).Name,StateStruct(val).Abbreviation);
statenameh = uicontrol('Style','text',...
'Units','Normalized',...
'Position',[0.6 0.8 0.3 0.1],...
'String',statename,...
'FontSize',30,...
'FontName','TimesNewRoman');
% Set up the state info display
capital = sprintf('Capital: %s',StateStruct(val).Capital);
largestcity = sprintf('Largest City: %s',StateStruct(val).LargestCity);
statehood = sprintf('Year of Statehood: %s',num2str(StateStruct(val).Statehood));
population = sprintf('Population: %s',num2str(StateStruct(val).Population));
area = sprintf('Area: %s',num2str(StateStruct(val).TotalAreaMiles));
nickname = sprintf('Nickname: %s',StateStruct(val).Nickname);
gdp = sprintf('GDP: %s',num2str(StateStruct(val).GDP));
capitalh = uicontrol('Style','text',...
'Units','Normalized',...
'Position',[0.5 0.7 0.5 0.1],...
'String',capital,...
'FontSize',20);
largestcityh = uicontrol('Style','text',...
'Units','Normalized',...
'Position',[0.5 0.6 0.5 0.1],...
'String',largestcity,...
'FontSize',20);
statehoodh = uicontrol('Style','text',...
'Units','Normalized',...
'Position',[0.5 0.5 0.5 0.1],...
'String',statehood,...
'FontSize',20);
populationh = uicontrol('Style','text',...
'Units','Normalized',...
'Position',[0.5 0.4 0.5 0.1],...
'String',population,...
'FontSize',20);
areah = uicontrol('Style','text',...
'Units','Normalized',...
'Position',[0.5 0.3 0.5 0.1],...
'String',area,...
'FontSize',20);
nicknameh = uicontrol('Style','text',...
'Units','Normalized',...
'Position',[0.5 0.2 0.5 0.1],...
'String',nickname,...
'FontSize',20);
gdph = uicontrol('Style','text',...
'Units','Normalized',...
'Position',[0.5 0.1 0.5 0.1],...
'String',gdp,...
'FontSize',20);
% Set up the flag display
url = StateStruct(val).Flag;
flag = imread(url);
axish = axes('Units','Normalized',...
'Position',[0.05 0.10 0.4 0.5]);
imagesc(flag)
set(axish,'Visible','off')
end
end
The loaderfn function just opens a .MAT file.

Best Answer

Inside your setup function you define
function infopage(~,~)
set(titleh,'Visible','off')
infopage;
end
as a nested function. The callback created by your setup function is going to return to this nested function, because nested functions have just about the highest priority. That nested function named infopage calls upon infopage, which is its own name. You have programmed in an infinite loop.
To call the outside infopage, you would need to change to
run('infopage')
which would run it as a script rather than as a function. That works because it happens to have no parameters and returns no result. If you needed to pass in parameters or get results then calling it would be a bit tricky.
The easiest way to avoid this problem is to not shadow the names of function you want to call upon. If you want to do something before calling that function, then name the intercepting routine something else.