MATLAB: Error: Error while evaluating UIControl Callback.

undefined function or variable

I am getting error :
Undefined function or variable 'SHOWNODES'.
Error while evaluating UIControl Callback
Can someone help me why I am getting this error and how to resolve it?
Also If I change the number of nodes per element from 4 to 8 . Then i am getting
error : Subscript indices must either be real positive integers or logicals.
Error in RectangularPlate22 (line 70)
X(:,iel) = coordinates(nodes(iel,:),1) ;
Help me resolve these two errors.
clc ; clear all ;
% Variables which can be changed
% Dimensions of the plate
L = 0.5 ; % Length of the Plate along X-axes
B = 0.5 ; % Breadth of the Plate along Y-axes
% Number of Elements required
Nx = 20 ; % Number of Elements along X-axes
Ny = 20 ; % Number of Elements along Y-axes
%----------------------------------------
% From here dont change
nel = Nx*Ny ; % Total Number of Elements in the Mesh
nnel = 4 ; % Number of nodes per Element
% Number of points on the Length and Breadth
npx = Nx+1 ;
npy = Ny+1 ;
nnode = npx*npy ; % Total Number of Nodes in the Mesh
% Discretizing the Length and Breadth of the plate
nx = linspace(0,L,npx) ;
ny = linspace(0,B,npy) ;
[xx yy] = meshgrid(nx,ny) ;
% To get the Nodal Connectivity Matrix
coordinates = [xx(:) yy(:)] ;
NodeNo = 1:nnode ;
nodes = zeros(nel,nnel) ;
% If elements along the X-axes and Y-axes are equal
if npx==npy
NodeNo = reshape(NodeNo,npx,npy);
nodes(:,1) = reshape(NodeNo(1:npx-1,1:npy-1),nel,1);
nodes(:,2) = reshape(NodeNo(2:npx,1:npy-1),nel,1);
nodes(:,3) = reshape(NodeNo(2:npx,2:npy),nel,1);
nodes(:,4) = reshape(NodeNo(1:npx-1,2:npy),nel,1);
% If the elements along the axes are different
else%if npx>npy
NodeNo = reshape(NodeNo,npy,npx);
nodes(:,1) = reshape(NodeNo(1:npy-1,1:npx-1),nel,1);
nodes(:,2) = reshape(NodeNo(2:npy,1:npx-1),nel,1);
nodes(:,3) = reshape(NodeNo(2:npy,2:npx),nel,1);
nodes(:,4) = reshape(NodeNo(1:npy-1,2:npx),nel,1);
end
%
% Plotting the Finite Element Mesh
% Initialization of the required matrices
X = zeros(nnel,nel) ;
Y = zeros(nnel,nel) ;
% Extract X,Y coordinates for the (iel)-th element
for iel = 1:nel
X(:,iel) = coordinates(nodes(iel,:),1) ;
Y(:,iel) = coordinates(nodes(iel,:),2) ;
end
% Figure
fh = figure ;
set(fh,'name','Preprocessing for FEA','numbertitle','off','color','w') ;
patch(X,Y,'w')
title('Finite Element Mesh of Plate') ;
axis([0. L*1.01 0. B*1.01])
axis off ;
if L==B
axis equal ;
end
% To display Node Numbers % Element Numbers
pos = [70 20 60 20] ;
ShowNodes = uicontrol('style','toggle','string','nodes','value',0,....
'position',[pos(1) pos(2) pos(3) pos(4)],'background','white','callback',...
'SHOWNODES(ShowNodes,ShowElements,coordinates,X,Y,nnode,nel,nodes)');
pos = get(ShowNodes,'position') ;
pos = [2*pos(1) pos(2) pos(3) pos(4)] ;
ShowElements = uicontrol('style','toggle','string','Elements','value',0,....
'position',[pos(1) pos(2) pos(3) pos(4)],'background','white','callback',....
'SHOWELEMENTS(ShowElements,ShowNodes,coordinates,X,Y,nel,nodes,nnode)');

Best Answer

You specified the callback as a character vector. Callbacks that are character vectors, are executed in the base workspace, and so only have access to variables defined in the base workspace.
The seemingly obvious change would be to
ShowElements = uicontrol('style','toggle','string','Elements','value',0,.... 'position',[pos(1) pos(2) pos(3) pos(4)],'background','white','callback',.... @(varargin) SHOWELEMENTS(ShowElements,ShowNodes,coordinates,X,Y,nel,nodes,nnode));
But that will not work. When you create an anonymous function, the value of the mentioned variables are captured as of the time of the call, and at that time, ShowElements has not yet been defined.
What would work though is
ShowElements = uicontrol('style','toggle','string','Elements','value',0,.... 'position',[pos(1) pos(2) pos(3) pos(4)],'background','white','callback',.... @(hObject,event) SHOWELEMENTS(hObject,ShowNodes,coordinates,X,Y,nel,nodes,nnode)');
The corresponding change will not work for the earlier ShowNodes, because the callback for it refers to ShowElements that would not have been defined yet.
The approach that will work for both is to create both the uicontrol without putting in the callbacks, so that the handles both get defined. Then you can set the Callback properties of the two to @(varargin) followed by the existing callback without the surrounding quote marks.