Ginput in a GUI

조회 수: 26 (최근 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
  댓글 수: 1
Matt Tearle
Matt Tearle 2011년 5월 18일
No, sorry. Not sure what changed.

댓글을 달려면 로그인하십시오.


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에서 Annotations에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by