Mouse click on Axes Problem
7 views (last 30 days)
Show older comments
Hello. I am trying to use the mouse click on an axes to drive the position of an xystage. I have created my a grid with identifying text:
axes(handles.axes1); cla reset
hold on
ax = gca;
ax.XGrid = 'on';
ax.YGrid = 'on';
xticks(1:1:13)
yticks([1:1:9])
xlim([1 13]);
ylim([1 9]);
ax.GridColor = [0 .5 .5];
ax.GridLineStyle = '--';
ax.GridAlpha = 0.5;
ax.Layer = 'top';
hold on;
format bank
startingRows = linspace(1, 8, 8);
startingCols = linspace(1, 12, 12);
% % Now get the starting integer rows / cols.
startingRows = int32(startingRows(1:end))
startingCols = int32(startingCols(1:end))
ct=0;
for i=1:length(startingRows)
for j=1:length(startingCols)
ct=ct+1;
%Add region number
xr=double(startingCols(j))+0.3;
yr=double(startingRows(i))+0.5;
hold on
text(xr,yr,[num2str(i),',',num2str(j)],'FontSize', 8, 'Color', [1 0 1]);
end
end
set(handles.axes1,'Visible','on');
set(handles.axes1,'ButtonDownFcn',@ImageClickCallback); %An alternative to axes ButtonDownfunction
I then want to be able to click anywhere on the grid and return the number sin the grid. Its fine just to return the coordinates of the mouse. I have tried the axes1 ButtondownFunction via:
axes(handles.axes1)
cpt = get(gca,'CurrentPoint')
pt = cpt(1,1:2)
x=round(pt(1))
y=round(pt(2))
But it only works before the grid and numbers are drawn on. I have read this only works when actually clicking on the grid and not areas inside i.e. the boxes - which is what I want.
0 Comments
Accepted Answer
Jan
on 12 Jun 2018
Edited: Jan
on 12 Jun 2018
It is prone to bugs to rely on the current axes object by cla and gca. You have the handle of the axes available, so use it. Replace:
axes(handles.axes1); cla reset
hold on
ax = gca;
by
ax = handles.axes1;
cla(handles.axes1, 'reset')
ax.NextPlot = 'add'; % EDITED, was 'on'
The format bank influences all following output to the command window. It is not useful here.
Replace
startingRows = linspace(1, 8, 8);
startingRows = int32(startingRows(1:end))
by the much simpler:
startingRows = 1:8;
(1:end) can be omitted at all, because it wastes time only.
I assume, the only problem with your code is, that the text objects shadow the axes, such that a click on them does not trigger the ButtonDownFcn of the axes in the background. You can let the text objects pass through the event by setting their 'HitTest' to 'off':
text(xr, yr, sprintf('%d,%d', i, j), 'FontSize', 8, 'Color', [1 0 1], ...
'HitTest', 'off');
Summary:
% ** UNTESTED CODE - WRITTEN IN THE FORUMS INTERFACE ONLY **
ax = handles.axes1;
cla(ax, 'reset')
ax.NextPlot = 'on'; % Equivalent to: hold on
ax.XGrid = 'on';
ax.YGrid = 'on';
ax.XTick = 1:13;
ax.YTick = 1:9;
ax.XLim = [1 13];
ax.YLim = [1 9];
ax.GridColor = [0 .5 .5];
ax.GridLineStyle = '--';
ax.GridAlpha = 0.5;
ax.Layer = 'top';
for i = 1:8
for j = 1:12
text(j + 0.3, i + 0.5, sprintf('%d,%d', i, j), ...
'FontSize', 8, 'Color', [1 0 1], ...
'HitTest', 'off');
end
end
ax.Visible = 'on';
ax.ButtonDownFcn = @ImageClickCallback;
And the callback:
function ImageClickCallback(AxesH, EventData)
cpt = get(AxesH, 'CurrentPoint');
pt = cpt(1, 1:2);
x = round(pt(1));
y = round(pt(2));
... what to do with x and y?
end
Using the dot notation "ax.Property = ..." only looks nicer, but is is no error to mix it with "set(ax, 'Property', ...)" and the more abstract functions like xticks and hold on.
5 Comments
Jan
on 22 Jan 2019
@Jason: The same as: hold on , but this uses the current axes. Look into the code of hold:
type hold
You can see, that this does some parsing and sets 'NextPlot' also. So I prefer the direct approach.
More Answers (0)
See Also
Categories
Find more on Graphics Object Programming in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!