Can I modify inputs for pushbutton callback

7 views (last 30 days)
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
Delphine Prevost
Delphine Prevost on 24 Jul 2017
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
Adam
Adam on 24 Jul 2017
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)

Jan
Jan on 21 Jul 2017
...
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
Jan
Jan on 24 Jul 2017
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.


Robert U
Robert U on 21 Jul 2017
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
Delphine Prevost
Delphine Prevost on 24 Jul 2017
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.
Robert U
Robert U on 24 Jul 2017
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 Migrate GUIDE Apps in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!