Mouse click on Axes Problem

7 ビュー (過去 30 日間)
Jason
Jason 2018 年 6 月 12 日
コメント済み: Jan 2019 年 1 月 22 日
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.

採用された回答

Jan
Jan 2018 年 6 月 12 日
編集済み: Jan 2018 年 6 月 12 日
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 件のコメント
Jason
Jason 2018 年 6 月 12 日
what does the following do:
ax.NextPlot = 'add';
Jan
Jan 2019 年 1 月 22 日
@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.

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeGraphics Object Programming についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by