More efficient way to insert a push button in a figure and run a function or a command.

Hi, I wrote the following function to plot x and y and when you press a button it calls the ginput of 2 coordinates and inserts the text of the result on the plot. The problem is that I had to create the ButtonDownFcn as an entire string to be evaluated. Ok, like that is working, but how can I be more efficient and call a function in a function to do that? Thank you very much and best regards Rafael
x=1:0.01:5;
y=sin(x);
function [ ] = Plot_with_ginput_buttonfn( x,y )
figure
plot(x,y)
% create a button to calculate the difference between 2 points
h = uicontrol('Position',[5 5 150 30],'String','Calculate xdiff',...
'Callback','uiresume(gcbf)');
h.Enable = 'Inactive';
h.ButtonDownFcn=['[ppm, intensity]=ginput(2);' ...
'J=abs(diff(ppm))*600;'...
'Jstr=sprintf(''J=%.1fHz'', J);' ...
'meanppm=abs(mean(ppm));' ...
'ppmstr=sprintf(''%.3f'', meanppm);'...
'text(meanppm, mean(intensity), {[''\delta'' ppmstr]; Jstr});'];
end

7 Kommentare

I'm not entirely sure I understand what you are asking or why you cannot just set your function on the 'Callback'. I've never used a ButtonDownFcn on a pushbutton as it sounds very counter-intuitive so I wouldn't actually know which gets called first either between it and the Callback
I've also never seen a function defined in that way. It would be a lot simpler to just use a function handle and define the function in a more regular manner. You can test it more easily that way too.
Note that the MATLAB documentation for callback functions states clearly: "Defining a callback as a character vector is not recommended."
Evaluating strings like that is slow, buggy, and complex. You should use a function handle, just as the MATLAB documentation recommends.
"how can I be more efficient and call a function in a function to do that?"
I created a function to give me a certain plot. Then, I create a button in this figure to run a set of commands when I press it. Like that it is working and I can make a plot and then run a set of commands when I press the button to calculate the difference between two peaks and make a text in the figure. I don't know the "right" way to do it, but this is working fine and I really want to learn the correct way to do this task. Thank you for your comment.
Thanks, I will take a look and read it carefully.
function [ ] = Plot_with_ginput_buttonfn( x,y )
figure
plot(x,y)
% create a button to calculate the difference between 2 points
h = uicontrol('Position',[5 5 150 30],'String','Calculate xdiff',...
'Callback','uiresume(gcbf)');
h.Enable = 'Inactive';
h.ButtonDownFcn=@Jcal;
function Jcal()
[ppm, intensity]=ginput(2);
J=abs(diff(ppm))*600;
Jstr=sprintf('J=%.1fHz', J);
meanppm=abs(mean(ppm));
ppmstr=sprintf('%.3f', meanppm);
text(meanppm, mean(intensity), {['\delta' ppmstr]; Jstr});
end
end
I did this but I am getting the following error when I press the button:
Error using Plot_with_ginput_buttonfn/Jcal
Too many input arguments.
Error while evaluating UIControl ButtonDownFcn
Now it is working fine, I added the x,y in the nested function
function Jcal(x,y)
and it works. Why? Do I need to add all arguments in the nested function as well?
As stated in the Callback Function Syntax section on this documentation page:
"Graphics callback functions must accept at least two input arguments:
  • The handle of the object whose callback is executing. Use this handle within your callback function to refer to the callback object.
  • The event data structure, which can be empty for some callbacks or contain specific information that is described in the property description for that object."

Melden Sie sich an, um zu kommentieren.

 Akzeptierte Antwort

Jan
Jan am 16 Okt. 2018
Bearbeitet: Jan am 17 Okt. 2018
What about using the Callback instead of the ButtonDownFcn?
function Plot_with_ginput_buttonfn( x,y )
figure
plot(x,y)
% create a button to calculate the difference between 2 points
h = uicontrol('Position',[5 5 150 30],'String','Calculate xdiff',...
'Callback', @JCal);
function JCal(ButtonH, EventData)
[ppm, intensity] = ginput(2);
J = abs(diff(ppm))*600;
Jstr = sprintf('J=%.1fHz', J);
meanppm = abs(mean(ppm));
ppmstr = sprintf('%.3f', meanppm);
text(meanppm, mean(intensity), {['\delta' ppmstr]; Jstr});
end
end

4 Kommentare

Great!!! That works fine. Thank you very much. BTW you wrote Jcal and JCal. Also, the code below work fine too. For that case, I didn't nested the function, and I changed the inputs of to ~. Keeping this discussion, is there any difference between nesting a function or creating a function in function for this case? I am confused with this two approaches. The two codes are giving precisely the same results, but which one is the best to use? Once again, thank you very much. Rafael
function [ ] = Plot_with_ginput_buttonfn( x,y )
figure
plot(x,y)
% create a button to calculate the difference between 2 points
h = uicontrol('Position',[5 5 150 30],'String','Calculate xdiff',...
'Callback', @JCal);
end
function JCal(~, ~)
[ppm, intensity] = ginput(2);
J = abs(diff(ppm))*600;
Jstr = sprintf('J=%.1fHz', J);
meanppm = abs(mean(ppm));
ppmstr = sprintf('%.3f', meanppm);
text(meanppm, mean(intensity), {['\delta' ppmstr]; Jstr});
end
Another point. I seem to me that you can use any argument in the second function, but the number of arguments must be equal or more than the number of arguments in the main function (the first function). That is so strange!
function [ ] = Plot_with_ginput_buttonfn( x,y )
figure
plot(x,y)
% create a button to calculate the difference between 2 points
h = uicontrol('Position',[5 5 150 30],'String','Calculate xdiff',...
'Callback', @JCal);
end
function JCal(fd,sdf,fdsfds,fdsf, sadjdhjsajd,fadsff, fdsafadsfa,adsafdsafa)
[ppm, intensity] = ginput(2);
J = abs(diff(ppm))*600;
Jstr = sprintf('J=%.1fHz', J);
meanppm = abs(mean(ppm));
ppmstr = sprintf('%.3f', meanppm);
text(meanppm, mean(intensity), {['\delta' ppmstr]; Jstr});
end
Adam
Adam am 17 Okt. 2018
Bearbeitet: Adam am 17 Okt. 2018
Callbacks must have 2 input arguments (as per the link Steven Lord shared above), which I usually call src and evt (but you can call them what you want, as you see). They represent the source object (the control that triggered the callback) and the event data which is usually useless, but for a small number of components carries useful information (e.g. tab group tab selected event tells you which tab you came from and which you are going to).
After that Matlab doesn't care what arguments you include except for the usual function rules that if you refer to something in the function that hasn't been declared or passed in as an argument it will error.
You can define any function with 15 arguments and use none of them in the function body if you really wish though!
Thank you very much. I read the links that Steven and Stephen shared, but I still had some doubts. Now, your comment clarifies everything to me. Now I got it. Thanks for all of you for helping me.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Kategorien

Mehr zu Entering Commands finden Sie in Hilfe-Center und File Exchange

Gefragt:

am 16 Okt. 2018

Bearbeitet:

Jan
am 17 Okt. 2018

Community Treasure Hunt

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

Start Hunting!

Translated by