Programatically (i.e. not using guide) accessing an edit box in another function

hi. I have create a figure and want to manually create a button and edit box on it too
%Add push button and edit boxes to analyse specific point
f1=figure;
ax1=subplot(1,1,1)
pb1 = uicontrol('Style', 'pushbutton',...
'String', {'Go'},...
'Position', [10 70 80 20],...
'Callback', @(src,evt) IntegratedIntensity( src, evt, ax1,handles ));
edx = uicontrol('Style', 'edit',...
'String', {'x pixel'},...
'Position', [10 40 40 20]);
I have connected the pushbutton to a function:
function IntegratedIntensity(source,event,ax,handles)
x=str2num(get(handles.edx,'String'));
However, when I call this function, the error indicates the edit box isn't recognised.
Reference to non-existent field 'edx'.

2 Comments

OK, I have tried all suggestions but not getting this to work, even with the handles.figure1 suggestion. To simplify, I programmatically create a checkbox and edit box via:
checkboxCumsum= uicontrol('Style', 'checkbox',...
'String', {'Cum Sum'},...
'Position', [620 0 80 30],...
'Callback', @(src,evt) CumSum( src, evt, ax1,handles.figure1 ));
edx = uicontrol('Style', 'edit',...
'String', {'95'},...
'Position', [700 5 40 20]);
I then create a function Cumsum as:
function CumSum(source,event,ax,handles)
val = source.Value
h=getappdata(0,'histog') %previously drawn histogram
if val==1
hline = findall(gca, 'type', 'line');
delete(hline);
counts=h.Values;
edges=h.BinEdges;
width=h.BinWidth;
ctrs=edges(1:end-1)+width/2;
%integrate histogram using cumsum
cs=cumsum(counts)
l=cs(end)
l1=0.95*l
[ii]=find(cs>l1)
ct=ctrs(ii(1))
hold on
lineH1=plot([ct ct],ylim,'b--','LineWidth',0.7);
text(ct+5,0.90*max(ylim), ['CumSum95=',num2str(ct,'%.0f')],'Fontsize',8,'Color','k','FontWeight','normal')
hold off
x=str2num(get(handles.edx,'String'))
end
I still get the error
No appropriate method, property, or field 'edx' for class 'matlab.ui.Figure'.
handles.figure1 is a handle to the figure (assuming that is what you have named the field if you are doing it programmatically - it seems to be judging by your error).
If it where in GUIDE you would get the handles structure from this as
handles = guidata( hGUI );
where hGUI would be the 4th argument to your CumSum function, not 'handles' because it is the handle to your GUI figure.
In a programmatic UI though it depends entirely how you have programmed it as to how you need to access things. If you use a nested function then you don't need to pass anything in often. If you do it in a class then the object will usually contain everything you want so is the only needed argument.

Sign in to comment.

 Accepted Answer

There are a few options, including
  1. Make IntegratedIntensity a nested function so it has access to the main function workspace
  2. Create your edit box before your pushbutton and pass its handle into the pushbutton callback along with ax1.
If you created a programmatic UI then 'handles' does not exist unless you explicitly add your components to a struct called handles so in both of the above options you should refer to the edit box simply as
edx
within the callback (assuming that is what you would call the variable you pass to the function in the 2nd option), rather than handles.edx
The fact you get a non-existent field error rather than a non-existent variable suggests 'handles' does exist in code you haven't shown us, but it certainly doesn't have the edit box attached to it.

11 Comments

So I've tried this:
pb1 = uicontrol('Style', 'pushbutton',...
'String', {'Go'},...
'Position', [10 70 80 20],...
'Callback', @(src,evt) IntegratedIntensity( src, evt, ax1,handles,edx));
edx = uicontrol('Style', 'edit',...
'String', {'x pixel'},...
'Position', [10 40 40 20]);
function IntegratedIntensity(source,event,ax,handles,edx)
x=str2num(get(edx,'String'));
But still get the same error message
It can't be exactly the same error message, the previous one was referring to a non-existent field on handles.
Where does this code sit though? Is it a nested function rather than just a local function? To be a nested function it must be declared inside the 'end' of the main function and thus must also be terminated by 'end' itself. Yours is not in the code you show so I assume this is actually just a local function.
Local functions come after the main function in a file and do not share its workspace, nested functions sit inside the main function and do.
Hi, sorry im not at a computer now. But the code is inside a push button call back.
But the pushbutton callback needs to be defined inside of the 'end' of your main function.
Im using GUIDE in which i have a pushbutton callback.
Inside this I create a figure with a push button and edit box (programmatically)
Its this 2nd push button created programmatically that I want to access the edit box contents.
Here is my full code inside a pushbutton call back created using GUIDE.
function pushbutton74_Callback(hObject, eventdata, handles)
% View Image Full Screen
IM=getimage(handles.axes4);
pos=myfigure(handles,800,500)
handles.f=figure('position',pos);
ax1=subplot(1,1,1)
n=str2double(get(handles.editn,'String'));
[high,low]=Autoscaleimage(handles,IM,n);
imshow(IM,[low, high],'Initialmagnification','fit','Border','loose');
hp=impixelinfo;
set(hp,'Position',[5 1 200 18]);
drawnow;
%Add push button and edit boxes to figure to analyse specific point
pb1 = uicontrol('Style', 'pushbutton',...
'String', {'Go'},...
'Position', [10 70 80 20],...
'Callback', @(src,evt) IntegratedIntensity( src, evt, ax1,handles));
handles.edx = uicontrol('Style', 'edit',...
'String', {'x pixel'},...
'Position', [10 40 40 20]);
handles.edy = uicontrol('Style', 'edit',...
'String', {'y pixel'},...
'Position', [60 40 40 20]);
handles.edP = uicontrol('Style', 'edit',...
'String', {'3'},...
'Position', [10 20 40 20]);
%update handles structure to figure
guidata(handles.f,handles)
function IntegratedIntensity(source,event,ax,handles)
x=str2num(get(handles.edx,'String'));
y=str2num(get(handles.edy,'String'));
d=str2num(get(handles.edP,'String'));
hold on
plot(x,y,'r+')
hold off;
The error is:
Reference to non-existent field 'edx'.
If you are using GUIDE then a nested function won't work, you would have to add 'end' to every function in the file and keep doing so for every new function which is totally impractical.
I assumed it was a programmatic GUI since you are creating components programmatically (also because your question title strongly suggests GUIDE is not involved!).
Simplest option is still to pass the edit box handle to the callback, but of course you have to create the editbox first. The callback can't be expected to know about it if it hasn't been created yet.
In my early days of using GUIDE I used to think that 'handles' is some magic object with wide-ranging scope and powers, but it isn't, it is simply a struct, like any other struct. There is some 'magic' goes on behind the scenes with GUIDE for it to be able to pass handles into all its own callbacks, but never pass handles directly into a callback that you create because your code will not include this 'magic'.
Like any other struct it has copy-by-value semantics - i.e. it will take a copy of the handles structure when you pass it to another function, it won't take a reference to it. Anything that you add to handles after that copy has been taken will not be included on the copy.
So in your code you pass handles to your callback, then you add further fields to it, including your edit box. The callback will not have these on its copy of handles.
The usual way to deal with this is to pass the handle of the main figure to the callback instead and then inside the callback you get the latest copy of the handles as
handles = guidata( hGUI )
(assuming you passed in the GUI handle as hGUI).
In your case this would work fine or you could pass in the individual editbox handles. Since there are 3 of them though I guess passing in the figure handle is neater.
Hi Adam. Thanks for your detailed explanation. Im a bit uncertain when you say
(assuming you passed in the GUI handle as hGUI)
Where do I actually do this?
pb1 = uicontrol('Style', 'pushbutton',...
'String', {'Go'},...
'Position', [10 70 80 20],...
'Callback', @(src,evt) IntegratedIntensity( src, evt, ax1,handles.figure1));
Just pass it in there. 'figure1' is the default tag for the main figure in GUIDE. I always change this because it is not a sensible tag, but if you haven't changed it then handles.figure1 should be the handle to the main figure.
Hi, why is it not a sensible Tag, what do you use, something like mainForm?
I always name it the same as the file. It's just convention, but I like my figure to be named something that is relevant to what it is and the filename obviously fits that purpose.
If you are only using the tag within its own UI though (as you should be generally) it doesn't really matter. If you tend to like to use findall and pull out handles from other GUIs and all that stuff (don't do it!!!) then having them all tagged figure1 is not very useful.

Sign in to comment.

More Answers (0)

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Asked:

on 27 Feb 2017

Commented:

on 4 Apr 2017

Community Treasure Hunt

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

Start Hunting!