Can I modify inputs for pushbutton callback

Hello, this is my first post and I am not a native english speaker, so please be cool !
I am currently trying to create a tool with an interface and I want to use the value entered in a EDIT uicontrol for the callback of a pushbutton. Here is a simplified version of my code which is divided in 2 m-files.
function mytest
figure
h1=uicontrol('style','Edit','string','1','Units','normalized','Position',[0.1 0.8 0.8 0.2],'backgroundcolor','w');
h2=uicontrol('style','Edit','string','XX','Units','normalized','Position',[0.1 0.1 0.8 0.2],'backgroundcolor','c');
a=1;
uicontrol('Style','PushButton','String','Get a','Units','normalized','Position',[0.1 0.6 0.8 0.15],'callback',@func_callback,'backgroundcolor','g','FontSize',12);
uicontrol('Style','PushButton','String','Disp a2','Units','normalized','Position',[0.1 0.4 0.8 0.15],'callback',{@func_compute,a,h2},'backgroundcolor','r','FontSize',12);
function func_callback(varargin)
a=str2num(get(h1,'string'));
end
end
function func_compute(~,~,a,h2)
b=a*a;
set(h2,'string',num2str(b));
end
For now, the value of "a" used while evaluating dispA pushbutton callback is always the initial value and not the new value computed when clicking GetA pushbutton. I know I could replace the input "a" by "h1" and then use "get(h1,'string') in func_compute but I would prefer not to since this is actually a vector with more than 50 coefficient (and so more than 50 EDIT uicontrol and not just one !
I hope I made myself clear and of course I hope you can help.
Thanks XXX

3 Comments

I'm not sure I understand the full setup well enough. If you want to use the edit box value in the push button callback then you need that callback to know about the editbox, i.e. it needs its handle. Since this is a programmatic UI rather than a GUIDE one the only way to achieve this is to pass in h1 as you say. But I don't really get what you mean about it being 50 edit controls since in the example it is only one. If there are 50 then which of the 50 is supposed to be linked top the pushbutton? You can pass in e.g. h1(27) if h1 is an arrray of 50 uicontrols and you just want the 27th to be linked to your given pushbutton.
Hi, thank you for your answer. I made a simple exemple with only one editbox for the question but in my actual application I have about 30 editbox which are used to allow the user to modify a very long vector "a" (100x1). But if the user want to modify another part of the vector (not one of the 30 with editbox), I made a popmenu linked with a 31st editbox which allow to modify any of the "a" vector. This is the reason why I cannot pass h1...h30, because there is this popmenu. I will try to understand the others answers below and if I don't manage to, I will come back to the monoscript version where "a" was a global variable and it worked. Thanks anyway
It would be easier to help if you could explain what the exact user workflow is. You have 31 edit boxes, 30 of them hard-linked to specific elements of some vector and then 1 which can be used for any element of the vector, which is controlled by a popup list? So the user is expected to change just one of these things and then push the button? Or can they change any number of the 31 edit boxes before pushing the button?
If I were confronted by that many edit boxes and a single pushbutton I would assume I could fill in all the edit boxes before pressing the button.

Sign in to comment.

Answers (2)

...
FigData.FigH = figure;
FigData.h1 = uicontrol('Style','PushButton','String','Get a', ...
'Units','normalized','Position',[0.1 0.6 0.8 0.15], ...
'callback',@func_callback,'backgroundcolor','g','FontSize',12);
FigData.h2 =uicontrol('Style','PushButton','String','Disp a2','Units','normalized', ...
'Position',[0.1 0.4 0.8 0.15],'callback', @func_compute, ...
'backgroundcolor','r','FontSize',12);
FigData.a = NaN;
guidata(FigData.FigH, FigData);
end
function func_callback(hObject, EventData)
FigData = guidata(hObject);
FigData.a = str2num(get(hObject, 'string'));
guidata(hObject, FigData);
end
function func_compute(hObject, EventData)
FigData = guidata(hObject);
b = FigData.a * FigData.a;
set(FigData.h2, 'string', num2str(b));
end
If you share the variable a is a nested function, you need to implement all callbacks, which use this variable, as nested functions. If you want an own M-file for a specific callback, you need another way to share the variable. Using a struct (here "FigData", usually called "handles") and guidata is a common method. Search in the forum for "share data between callbacks".
Hint: Searching in the forum before asking a new question is recommended and efficient.

4 Comments

Hi ! Thank you for taking some time to answer me. I guess you have a lot of people asking questions without checking help and forum before...this is not my case. The problem is I don't understand the guidata function and what is an eventdata. I learned matlab on my own and here I found my limits. The application I am developping started as a small interface just for me and grew a lot bigger with time especially with nested functions. I now want to share this application with friends and I wanted to make the code "cleaner" and easier to understand by making nested functions normal functions in their own files. Unfortunately, this is where everything blew up and nothing works anymore. Anyway, thanks for your answer, which contains stuff I had already read but not understood. You cannot help stupid people. I will try to understand it.
Stephen23
Stephen23 on 24 Jul 2017
Edited: Stephen23 on 24 Jul 2017
" I wanted to make the code "cleaner" and easier to understand by making nested functions normal functions in their own files."
What is wrong with using nested functions? They are reasonably efficient, are not too bad to debug, and will work on any version since MATLAB 7.
guidata(handle, Data) stores the contents of the variable Data in the parent figure of the GUI object addressed by handle. To be exact the property "ApplicationData" is used for storing, but this detail does not matter.
Data = guidata(handle) obtains the formerly stored value.
EventData is a struct provided for each callback function, which describes the event, which has triggered the callback. E.g. for the WindowsKeyPressFcn this contains the currently pressed keys. For a timer callback, it contains some information about the timer, e.g. the number of calls etc. In many codes the EventData can be ignored.
People who are learning are not stupid.

Sign in to comment.

Just to add a solution for external function use (in case you want to reuse external functions instead of rewriting nested ones):
function mytest
GUI.a = 1;
GUI.fh = figure;
GUI.h1 = uicontrol('style','Edit',...
'string','1',...
'Units','normalized',...
'Position',[0.1 0.8 0.8 0.2],...
'backgroundcolor','w',...
'Tag','EditField');
GUI.h2 = uicontrol('style','Edit',...
'string','XX',...
'Units','normalized',...
'Position',[0.1 0.1 0.8 0.2],...
'backgroundcolor','c',...
'Tag','EditField2');
GUI.h3 = uicontrol('Style','PushButton',...
'String','Disp a2',...
'Units','normalized',...
'Position',[0.1 0.4 0.8 0.15],...
'callback',{@func_compute,GUI.fh},...
'backgroundcolor',...
'r','FontSize',12);
end
function func_compute(~,~,FigHandle)
UICtrlIn = findobj(FigHandle,'Tag','EditField');
UICtrlOut = findobj(FigHandle,'Tag','EditField2');
a = str2double(UICtrlIn.String);
b = a * a;
UICtrlOut.String = num2str(b);
end
In that case the "get a" button can be omitted.

3 Comments

Keeping hold of a handle and passing it directly is always better (faster) than having to do a findobj to pick it back up though, in general.
Thanks for your answers, I agree with Adam and I don't really like the findobj solution, but it works ! If I don't understand Jan Simon answer, I will do that.
If you don't like to pass all figure handle, which makes it easier to pick any figure object you might want to modify later on, you can pass handles of you edit fields directly (as can be adapted from my answer):
function mytest
GUI.a = 1;
GUI.fh = figure;
GUI.h1 = uicontrol('style','Edit',...
'string','1',...
'Units','normalized',...
'Position',[0.1 0.8 0.8 0.2],...
'backgroundcolor','w',...
'Tag','EditField');
GUI.h2 = uicontrol('style','Edit',...
'string','XX',...
'Units','normalized',...
'Position',[0.1 0.1 0.8 0.2],...
'backgroundcolor','c',...
'Tag','EditField2');
GUI.h3 = uicontrol('Style','PushButton',...
'String','Disp a2',...
'Units','normalized',...
'Position',[0.1 0.4 0.8 0.15],...
'callback',{@func_compute,GUI.h1,GUI.h2},...
'backgroundcolor',...
'r','FontSize',12);
end
function func_compute(~,~,InHandle,OutHandle)
a = str2double(InHandle.String);
b = a * a;
OutHandle.String = num2str(b);
end
Works same as above without "findobj()". Nevertheless, I find the discussion about "faster" solution in terms of GUIs quite academic since we talk about ms which can not be mentioned by any human user.

Sign in to comment.

Categories

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

Tags

Asked:

on 21 Jul 2017

Community Treasure Hunt

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

Start Hunting!