Mouse click on Axes Problem

9 visualizaciones (últimos 30 días)
Jason
Jason el 12 de Jun. de 2018
Comentada: Jan el 22 de En. de 2019
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.

Respuesta aceptada

Jan
Jan el 12 de Jun. de 2018
Editada: Jan el 12 de Jun. de 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 comentarios
Jason
Jason el 12 de Jun. de 2018
what does the following do:
ax.NextPlot = 'add';
Jan
Jan el 22 de En. de 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.

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Graphics Object Programming en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by