Ginput in a GUI

24 次查看(过去 30 天)
Mel
Mel 2011-5-16
Hi, How can I restrict the selection of ginput to the figure in the GUI (rather than the entire GUI). Also as an aside, how can I store that information and export it into excel all within the GUI .m file.
  2 个评论
B_Richardson
B_Richardson 2011-7-6
Hello, did you ever solve your problem? I am attempting to accomplish somewhat the same thing?
Pedro Teodoro
Pedro Teodoro 2013-1-12
Try this,
This function works as ginput but it is adapted to be used in GUIs. It restrict the selection of ginput in the specified axes.

请先登录,再进行评论。

回答(6 个)

Matt Tearle
Matt Tearle 2011-5-16
Can't find the answer where I shared this before, so I'll just copy-n-paste. This is code that works around the limitations of ginput. The magic occurs in the functions changepointer and getpoints. This isn't the most efficient way to do this (most of the calculations in changepointer should be done in the parent function), but it should give an idea of how to mimic ginput.
function getgraphinput
hf = figure;
ha = axes('position',[0.1 0.3 0.8 0.6]);
x = linspace(0,1);
hp = plot(x,sin(5*pi*x));
set(hp,'hittest','off')
hstart = uicontrol('style','pushbutton','string','Start',...
'units','normalized','position',[0.2 0.1 0.2 0.1],...
'callback',@startgin);
hstop = uicontrol('style','pushbutton','string','Done',...
'units','normalized','position',[0.6 0.1 0.2 0.1],...
'callback',@stopgin,'enable','off');
function startgin(hObj,handles,eventdat)
set(hObj,'Enable','off')
set(hstop,'enable','on')
set(hf,'WindowButtonMotionFcn',@changepointer)
set(ha,'ButtonDownFcn',@getpoints)
end
function stopgin(hObj,handles)
set(hObj,'Enable','off')
set(hstart,'enable','on')
set(hf,'Pointer','arrow')
set(hf,'WindowButtonMotionFcn',[])
set(ha,'ButtonDownFcn',[])
xy = getappdata(hf,'xypoints');
line(xy(:,1),xy(:,2))
end
function changepointer(hObj,handles)
axlim = get(ha,'Position');
fglim = get(hf,'Position');
x1 = axlim(1)*fglim(3) + fglim(1);
x2 = (axlim(1)+axlim(3))*fglim(3) + fglim(1);
y1 = axlim(2)*fglim(4) + fglim(2);
y2 = (axlim(2)+axlim(4))*fglim(4) + fglim(2);
pntr = get(0,'PointerLocation');
if pntr(1)>x1 && pntr(1)<x2 && pntr(2)>y1 && pntr(2)<y2
set(hf,'Pointer','crosshair')
else
set(hf,'Pointer','arrow')
end
end
function getpoints(hObj,~,~)
cp = get(hObj,'CurrentPoint');
line(cp(1,1),cp(1,2),'linestyle','none','marker','o','color','r')
xy = getappdata(hf,'xypoints');
xy = [xy;cp(1,1:2)];
setappdata(hf,'xypoints',xy);
end
end
EDIT TO ADD
Sorry to make this balloon, but this might be preferable... here's a function that can stand alone in place of ginput. It mostly mimics ginput except that (1) the first input should be the handle to an axes object, and (2) if a number of points isn't specified, it defaults to 1.
function varargout = ginput_ax(ha,n)
if nargin<2
n=1;
end
k = 0;
xy = zeros(n,2);
hf = get(ha,'parent');
figure(hf);
set(hf,'WindowButtonMotionFcn',@changepointer)
set(ha,'ButtonDownFcn',@getpoints)
hp = get(ha,'children');
ht = get(hp,'hittest');
set(hp,'hittest','off')
axlim = get(ha,'Position');
fglim = get(hf,'Position');
x1 = axlim(1)*fglim(3) + fglim(1);
x2 = (axlim(1)+axlim(3))*fglim(3) + fglim(1);
y1 = axlim(2)*fglim(4) + fglim(2);
y2 = (axlim(2)+axlim(4))*fglim(4) + fglim(2);
waitfor(hf,'WindowButtonMotionFcn',[])
if iscell(ht)
for jj=1:length(ht)
set(hp(jj),'hittest',ht{jj})
end
else
set(hp,'hittest',ht)
end
if nargout==2
varargout{1} = xy(:,1);
varargout{2} = xy(:,2);
else
varargout{1} = xy;
end
function changepointer(~,~)
pntr = get(0,'PointerLocation');
if pntr(1)>x1 && pntr(1)<x2 && pntr(2)>y1 && pntr(2)<y2
set(hf,'Pointer','crosshair')
else
set(hf,'Pointer','arrow')
end
end
function getpoints(hObj,~,~)
cp = get(hObj,'CurrentPoint');
k = k+1;
xy(k,:) = cp(1,1:2);
if k==n
set(hf,'Pointer','arrow')
set(hf,'WindowButtonMotionFcn',[])
set(ha,'ButtonDownFcn',[])
end
end
end
  3 个评论
Matt Tearle
Matt Tearle 2011-5-16
Copy changepointer and getpoints as nested functions, just as I have here, and set the 'WindowButtonMotionFcn' property of your figure and the 'ButtonDownFcn' property of your axes, like I did inside startgin.
Matt Tearle
Matt Tearle 2011-5-16
See above edit. You can copy/paste this into a separate file, then call it just like you'd call ginput.

请先登录,再进行评论。


Paulo Silva
Paulo Silva 2011-5-16

Mike Loucks
Mike Loucks 2011-5-18
Matt, Thanks for this, it helped me a lot. I am not getting the croshairs to show up though. You mention setting windowbuttonmotionfcn of the figure, but I'm not sure what to set it to. It looks like maybe you set that in the code, but I'm not seeing the crosshairs.
I've had a heck of a time with ginput. It works fine in my older matlab code, but I'm running a version of that code now in Matlab Engine (being called from an external program) and I can't get ginput to ever act on the axes in the figure I want (there is only one figure, and only one axes). This is consistent with other matlab functions I'm using (contour, and associated graphing utilities). Previously, I could use the "axes" call once and all my contour calls went to the right place. Now, every single call that plots must have a direct reference to the axes or they will create another figure and graph there (useless). ginput doesn't take a direct reference, (and any attempt to direct focus for it fails), so the only thing I have that works is your stuff here.
Do you have any understanding of why this might be?
Thanks,
Mike

Mike Loucks
Mike Loucks 2011-5-18
Update, the cross-hairs do show up, but only over a very small portion at the top of my figure.
  3 个评论
Matt Tearle
Matt Tearle 2011-5-18
Er, wait, maybe I misunderstood. Do you mean the cursor turns into a crosshair only over a small portion of the figure window? That's weird. Could be a bug in my code. Do you have subplots, perhaps? It should turn into crosshairs anyone inside the axes, and be a regular pointer anywhere else in the figure window.
If you move the figure window after calling ginput_ax, that would probably mess it up.
Keerthi Kumar
Keerthi Kumar 2013-6-5
As Mike mentioned there was a problem with the cross hair. The problem was when you read out the position of the GUI figure window, the unit was not in pixel and pixels are used later to identify the axes region. I solved the problem by changing the unit to pixels before reading the position values.
oldUnits = get(hf,{'units'});
set(hf,{'units'},{'pixels'});
fglim = get(hf,'Position');
set(hf,{'units'},oldUnits);

请先登录,再进行评论。


Mike Loucks
Mike Loucks 2011-5-18
I have a figure with a graph area that covers only about 50% of the figure (the rest are buttons and text fields for output). The cross-hair only exists over a very small portion of my figure, and only when I place it in a particular place on one of my monitors! It's quite weird, I almost didn't see it. I did move the figure window though.
Should I do anything to the figure definition itself, or should the code change the crosshairs properly?
  1 个评论
Mike Loucks
Mike Loucks 2011-5-18
I changed your "changepointer" function so that the if statement always sets the pointer to fullcrosshair, and now it seems to work. It's not confined to the axes (but neither was the original function). Of course that was the original purpose of this post, but my issue was slight different, in that I couldn't get ginput to work at all.

请先登录,再进行评论。


Divakar Roy
Divakar Roy 2012-11-13
I have just uploaded to file-exchange, codes that are supposed to solve the original problem of restricting the selection of ginput to the figure in the GUI. Here's the link - http://www.mathworks.com/matlabcentral/fileexchange/38997 . Would appreciate to know if the codes are any help to people still interested in the problem.

类别

Help CenterFile Exchange 中查找有关 Graphics Object Properties 的更多信息

标签

Community Treasure Hunt

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

Start Hunting!

Translated by