MATLAB Answers

Reference to non-existent field

27 views (last 30 days)
Hi folks,
Building my first GUI programmatically and hitting a snag early on.
Can anyone tell me why I am getting the error
Reference to non-existent field 'popbutt2'.
Error in maingui/updateAxes (line 83)
yColNum = get(hs.popbutt2, 'value');
Error in maingui/popbutt1 (line 93)
updateAxes(hObject, eventdata, hs)
Error while evaluating UIControl Callback
In the code below:
function maingui
hs = addcomponents;
hs.Fig.Visible = 'on';
%%Create tabbed GUI
function hs = addcomponents
hs.hFig = figure('Name', 'Main', ...
'Position', ...
[20 100 1870 850]);
s = warning('off', 'MATLAB:uitabgroup:OldVersion');
%%Build Tabs
hs.TabGroup = uitabgroup('Parent',hs.hFig, 'Position', [ .01 .01 .98 .975 ]);
warning(s);
hs.Tabs(1) = uitab('Parent',hs.TabGroup, 'Title',' Preprocessing ');
hs.Tabs(2) = uitab('Parent',hs.TabGroup, 'Title',' Data ');
hs.Tabs(3) = uitab('Parent',hs.TabGroup, 'Title',' Report ');
set(hs.TabGroup, 'SelectedTab',hs.Tabs(1));
hs.TextBox = uicontrol('style','text', 'Position', [ 800 820 250 30] );
set(hs.TextBox,'String',' Main Processing Interface', ...
'Units', 'Characters', 'FontSize', 14, 'ForegroundColor', [ 0 0 0]);
%%Create Tab 1 Panels
%# populate tabs with UI components
hs.DataPanel1 = uipanel('Parent', hs.Tabs(1), 'Position', [.01 .01 .98 .98], 'BackgroundColor', 'white');
hs.DataPanel2 = uipanel('Parent', hs.DataPanel1, 'Position', [ .01 .9 .4 .08]);
%DataPanel3 = uipanel('Parent', DataPanel2, 'Position', [ .3 .3 .55 .6], 'BackgroundColor', 'white');
hs.textload = uicontrol('Style','text', 'String','No File Currently Loaded', ...
'Parent',hs.DataPanel2, 'Position', [ 130 15 450 30], 'FontSize', 12);
set(hs.textload,'callback', {@loadbutt1, hs});
% Plot 1
hs.ax1 = axes('Parent', hs.DataPanel1, 'units', 'normalized', 'Position', [.1 .5 .3 .3], 'box', 'on');
% X Axis Popup for Plot 1
hs.popbutt1 = uicontrol('Style','popupmenu', 'String','*', ...
'Parent',hs.Tabs(1), 'Position', [40 500 100 100]);
set(hs.popbutt1,'callback',{@popbutt1,hs});
% Y Axis Popup for Plot 1
hs.popbutt2 = uicontrol('Style','popupmenu', 'String','*', ...
'Parent',hs.Tabs(1), 'Position', [40 400 100 100]);
set(hs.popbutt2,'callback',{@popbutt2,hs});
% Load Data Button
hs.loadbutt1 = uicontrol('Style','pushbutton', 'String','Load Data', ...
'Parent',hs.DataPanel2, 'Position', [ 10 18 100 30]);
set(hs.loadbutt1,'callback',{@loadbutt1,hs});
% Filename
end
% Executes on button press in loadbutt1
function hs = loadbutt1(hObject, eventdata, hs)
hs.fileName = uigetfile('*.*');
guidata(hObject, hs);
set(hs.textload,'string',hs.fileName);
setpopmenuString(hs.popbutt1, eventdata, hs);
setpopmenuString(hs.popbutt2, eventdata, hs);
guidata(hObject, hs);
[numbers, colNames] = xlsread(hs.fileName);
hs.numbers = numbers
updateAxes(hObject, eventdata, hs);
guidata(hObject, hs);
end
% Set Figure 1 Axis as per XLS Row 34
function hs = setpopmenuString(hObject, eventdata, hs)
guidata(hObject, hs);
fileName = hs.fileName;
[numbers, colNames] = xlsread(hs.fileName);
hs.numbers = numbers
colNames2 = colNames(34,:)';
set(hObject,'string', colNames2);
guidata(hObject, hs);
end
% XLSRead to Populate Popupmenu Columns
function [x,y]= readExcelColumns(fileName, xColNum, yColNum)
a = xlsread(fileName);
x = a(:,xColNum);
y = a(:,yColNum);
end
% Plotting Function for Ax1
function hs = updateAxes(hObject, eventdata, hs)
guidata(hObject, hs);
xColNum = get(hs.popbutt1, 'value');
yColNum = get(hs.popbutt2, 'value');
x = hs.numbers(:,xColNum);
y = hs.numbers(:,yColNum);
fileName = hs.fileName;
[x,y]= readExcelColumns(fileName, xColNum, yColNum);
plot(hs.ax1, x,y)
end
function hs = popbutt1(hObject, eventdata, hs)
updateAxes(hObject, eventdata, hs)
end
function hs = popbutt2(hObject, eventdata, hs)
updateAxes(hObject, eventdata, hs)
end
end
Apologies if I am missing some protocol here, would appreciate any clues or tips at all.
I have used the Debugger and when I pause on
function hs = updateAxes(hObject, eventdata, hs)
guidata(hObject, hs);
xColNum = get(hs.popbutt1, 'value');
the last line, I can see the 'hs' structure doesn't include popbutt2, I'm just not sure why...
Matt

Accepted Answer

Walter Roberson
Walter Roberson on 20 Dec 2015
When you call
set(hs.popbutt1,'callback',{@popbutt1,hs});
then the 'hs' that is passed in to popbutt1 is the hs as it existed at the time of the set(). Another that was stored in 'hs' after that will not exist in the hs that the callback receives.
When you name a variable in constructing an anonymous function or constructing a callback like that, the value of the variable is what is recorded, not the name of the variable.
Also, you need to understand that callbacks of this type cannot return values. There are very few types of callbacks that can return values.
You appear to be using "end" statements that match your "function" statements, so I recommend you use shared variables. Initialize hs in your maingui function and then after that, put in nested functions that assume that hs exists without having it passed.
function maingui
hs = [];
add_components();
hs.Fig.Visible = 'on';
function addcomponents
hs.hFig = figure('Name', 'Main', ...
'Position', [20 100 1870 850]);
s = warning('off', 'MATLAB:uitabgroup:OldVersion');
....
set(hs.textload, 'callback', @loadbutt1); %do not name hs in callback
...
set(hs.popbutt1, 'callback', @popbutt1); %do not name hs in callback
...
end
% Executes on button press in loadbutt1
function loadbutt1(hObject, eventdata) %do not name hs in arguments
hs.fileName = uigetfile('*.*');
%do not guidata here
set(hs.textload,'string',hs.fileName);
setpopmenuString(hs.popbutt1, eventdata); %do not pass hs
setpopmenuString(hs.popbutt2, eventdata); %do not pass hs
%do not guidata here
[numbers, colNames] = xlsread(hs.fileName);
hs.numbers = numbers
updateAxes(hObject, eventdata); %do not pass hs
end
... define other functions that read and write hs and do not guidata() it
end %end matching function maindata
as long as the variable hs is defined before any nested routine that needs its then the nested routines can read and write the value as needed and will always get the current value -- "hs" will effectively be global to them (but not accessible outside the nested routines.)

More Answers (2)

Image Analyst
Image Analyst on 20 Dec 2015
Ah, the difficulties of rolling your own. You will encounter lots of things like this if you continue. To fix this one, evidently you're calling updateAxes() before the popbutt2 button gets created. But the problem is that updateAxes() references hs.popbutt2, which doesn't exist yet. Step through with the debugger to find out when updateAxes() gets called first, and make sure that you've created popbutt2 before that.
Why not just use GUIDE or a ready-made framework to get a fast start like this one: http://www.mathworks.com/matlabcentral/fileexchange/24224

Matthew Zelko
Matthew Zelko on 20 Dec 2015
Thanks guys. It seems my variables were indeed being called prematurely so I added some sets and it's working well.
Really appreciate it.

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by