Loren on the Art of MATLAB
February 15th, 2006
Nested Function Interaction with Global Variables
Recently on two different occasions, people have asked me to help debug their nested function code. I was struck by the similarity of their problems and today will show you the problem and some solutions.
The problem, simply stated, is this. The users wrote GUIs using nested functions and brought up a single instance which ran fine. Then they brought up a second instance while the first one was running, and ran the second one. So far, so good. Then each user went to the original GUI window and pushed a button. To the surprise of those watching, the action all happened in the second GUI from that moment forward, regardless of which GUI's button was pressed. What was happening?
The users each wrote GUIs using code with this sort of code structure.
function myGUI
global hLines hColor
hfig = figure('name','Changing line colors');
hax = axes('parent',hfig);
init();
function init(varargin)
hLines = plot(hax,magic(3));
hColor = uicontrol('style','pushbutton',...
'string', 'Change line colors', ...
'units','normalized',...
'position',[0.01 0.01 0.25 0.05],...
'callback',@changeColor);
end
function changeColor(varargin)
colors = {rand(1,3); rand(1,3); rand(1,3)};
set(hLines, {'Color'}, colors);
end
end
Notice that some of the handles are declared to be global. Both the init and myStop functions need access to this information, but the main function myGUI doesn't know about them. However, declaring them global (persistent would have the same effect here since there's only one file) is what's causing the first and second instances to both point to the line and uicontrol handles in the second figure, causing incorrect interactions.
How can you stop that from happening? Two ways:
-
Instead of declaring the shared variables global, simply initialize them. Replace:
global hLines hColor
with
hLines = []; hColor = [];
-
Here's a solution that is perhaps even more elegant. Since init only gets called once, don't make it a nested function and instead include the code directly in myGUI. Since that code runs when myGUI is created, the variables in question are automatically initialized to their correct values and are now visible to the changeColor nested function. The code is now slightly shorter, possibly even more readable, and doesn't have unpleasant side effects.
function myGUIclean
% initialize GUI
hfig = figure('name','Changing line colors');
hax = axes('parent',hfig);
hLines = plot(hax,magic(3));
hColor = uicontrol('style','pushbutton','units','normalized',...
'position',[0.01 0.01 0.25 0.05],'string','Change line colors',...
'callback',@changeColor);
% callback for pushbutton
function changeColor(varargin)
colors = {rand(1,3); rand(1,3); rand(1,3)};
set(hLines, {'Color'}, colors);
end
end
For a more complex GUI example, see The MathWorks News & Notes - January 2006 article and find the code on the MATLAB File Exchange.
12:16 pm |
Posted in Function Handles, New feature |
Permalink |
You can follow any responses to this entry through the RSS 2.0 feed.
You can skip to the end and leave a response. Pinging is currently not allowed.
Leave a Reply
|
 |
Loren Shure works on design of the MATLAB language at The MathWorks. She writes here about once a week on MATLAB programming and related topics. 
|
 |
|
Hi, I think your example with nested are nice and i cant do the same.
I am running Matlab6 but no way to share variable efficiently
-for exemple I run the nested function ‘taxdemo’
taxDemo(30) %%Matlab example
” ??? Undefined function or variable ‘AdjustedIncome’.”
Furthermore, when I am inside a function into i cannot access global variables defined in the main workspace, with the exception of nested global variables, for exemple somthing like that:
function param=opt(goal)
global G
G=goal;
…..
param = lsqnonlin(@circuit,Z0,LB,HB,cond);
function F = circuit(Z)
%acces global
end
end
Nested functions are a new feature in MATLAB 7 which is why the code didn’t work in MATLAB 6 when you tried it there.
I recommend you read the documentation on using global variables to understand how to access them. In each workspace that you want to see a particular global variable, you must declare that before making reference to it. This includes functions and the base workspace.
Hi
I have built my code in MATLAB 7. I have a problem. I used global variables in the function for example img_global. Now by using imread, I get the input image and using imshow create an instance showing image. Later in the function, I create another using figure(’Name’, ‘Label’) alongwith the msgbox of the result. msgbox and seconf figure is there but first figure disappears. Please help