ButtonDownFcn on Axes after imshow

My ButtonDownFcn for my axes does not work after I call imshow
ax = axes;
set('ButtonDownFcn', @(h,e) disp('Hello'));
imshow(img, 'Parent', ax);
Of course I've read the myriad other post with the same problem and the solution seems to be something like this:
ax = axes;
set('ButtonDownFcn', @(h,e) disp('Hello'));
hold on
h = imshow(img, 'Parent', ax);
set(h, 'HitTest', 'off');
When I do this, it does indeed turn off the hittest for the image, but unfortunately when I click the image I am hitting the figure, not the axes. This is confirmed by the following:
>> hittest()
ans =
Figure (1) with properties:
Number: 1
Name: ''
Color: [0.9400 0.9400 0.9400]
Position: [1232 1208 570 450]
Units: 'pixels'hittest()
So how do I force my click to hit the axes and not the figure? My only work around is to set the ButtonDownFcn for the image itself, but this is really not desirable because after some user input I need to overlay (with transparency) a new image which then becomes the top image. I could then set an identical ButtonDownFcn on this new image, but I'm hoping for a better solution than this work around.

 Accepted Answer

Make sure that hittest and pickableparts is set for the axes.
imshow() does a lot of things behind your back. I prefer to use image()

7 Comments

Thank you! The following worked for me!
set(ax, 'PickableParts', 'all')
I guess this is because the result of imshow fills the entire axis, so when PickableParts is set to its default of 'visible' the click will never hit the axis because it is not visible.
So which callback gets called? What if you had a callback for the figure (which might have one), the axes, and the image (which I think won't have one by default though you could set one up)? And you click on the image, which callback gets executed?
When I click the image the axis callback gets executed. I have buttons in the figure with callbacks that work fine when I click them, but the above solution lets me grab the axis after an image have been shown on top of it.
I know this thread is a little bit old, but I'm having a very similar problem that this didn't resolve and I was wondering if you could comment on why. I'm connected to a webcam, and updating an axis handles.axesCamera1 after taking a snapshot in a loop. The relevant code is below:
if true
while handles.numClicked < 1
set(handles.axesCamera1,'PickableParts','all','ButtonDownFcn', @ondown);
handles.imgCurr = snapshot(handles.cam);
imshow(handles.imgCurr,'Parent',handles.axesCamera1);
end
end
and ondown is simply set to show text 'clicked'
if true
function ondown(~,~)
% % get current mouse position
% % assignin('VideoAnalysis','handles',handles);
% % handles.cp = get(handles.axesCamera1,'currentpoint');
% % handles.cp = handles.cp(1,:);
% % handles.numClicked = handles.numClicked + 1;
'clicked'
end
I've also tried moving the set function to outside the loop - is there something I'm missing to get the click to register on the axis?
I am also struggling with this. Did you figure it out?
Alex Nieva
Alex Nieva on 12 Jul 2018
Edited: Alex Nieva on 12 Jul 2018
For me I had everything in place except the hold on after setting up the axes. Then it worked.
The difficulty with the very first version of the code the user posted is that it sets up something on the axes and then calls imshow. When imshow detects that it is being called on an axes that is in the default position for a single axes then imshow does not merely change the content of the axes but instead deletes the axes. Which of course gets rid of the callback that has been set on the axes. imshow does not do the deletion if hold on is in effect.
Also, of course, imshow is adding the image object, which covers up the axes, so for the axes button callback to work on the image you have to configure for hits to get passed through the image object.

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 26 Apr 2017
Create a callback function and specify that callback function in the callback of the figure, not the axes.

1 Comment

Yes, this is another work around, but it turns out that setting pickable parts to 'all' achieved exactly what I was looking for :). Thanks for the suggestion!

Sign in to comment.

Categories

Find more on Interactive Control and Callbacks 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!