Drag and drop plot (inset) within another plot?

Hi, sorry if this is really obvious!
I am trying to interactively move one plot within another figure using drag and drop mouse operations.
I am using the following function to create the interactive behaviour (below):
As you can hopefully see, it allows me to successfully move both a text box or the graph axis around a figure window succesfully and log x + y co-ordinates.
What I am trying to achieve is to move the plot once it has an image stored within it.
I can make the plot contain an image easily using this answer/place a figure within a figure: https://uk.mathworks.com/matlabcentral/answers/60376-how-to-make-an-inset-of-matlab-figure-inside-the-figure#comment_654093
However, when I do so I lose the interactive element! This happens as soon as any content is added to the axis.
I think it may be because the axis and content are stored as seperate objects but I am unsure?
I am aware of the various functions on FEX, Moveit etc etc, however I am trying to do it in this manner as I need to plug this function into a reasonably heavy backend so am trying to avoid messing around making things into patches and so on.
Thanks in advance! And again, sorry if i've missed the obvious, been staring at this for awhile now...
function drag_drop
dragging = [];
orPos = [];
f = figure('WindowButtonUpFcn',@dropObject,'units','normalized','WindowButtonMotionFcn',@moveObject);
a = annotation('textbox','position',[0.2 0.2 0.2 0.2],'String','...','ButtonDownFcn',@dragObject);
a1 = axes('Position',[.7 .7 .2 .2], 'ButtonDownFcn', @dragObject)
function dragObject(hObject,eventdata)
dragging = hObject;
orPos = get(gcf,'CurrentPoint');
end
function dropObject(hObject,eventdata)
if ~isempty(dragging)
newPos = get(gcf,'CurrentPoint');
posDiff = newPos - orPos;
set(dragging,'Position',get(dragging,'Position') + [posDiff(1:2) 0 0]);
dragging = [];
end
end
function moveObject(hObject,eventdata)
if ~isempty(dragging)
newPos = get(gcf,'CurrentPoint');
posDiff = newPos - orPos;
orPos = newPos;
set(dragging,'Position',get(dragging,'Position') + [posDiff(1:2) 0 0]);
disp(orPos)
end
end
end

 Accepted Answer

Try setting 'HitTest','off' for whatever objects you add to the axes. This will allow mouse clicks to pass through to the axes underneath (so that the axes ButtonDownFcn executes), rather than being captured by the new object.

6 Comments

hmm, sounds promising. Thanks!
I can't quite see where i'm putting the call though? Say i'm loading the image like (see below):
I can't chuck it in the imshow command or it'll fail, I think what I need is someway to *explicitly* add it (the image, also the same for data I suppose?) to the axes call for that to work perhaps?
a1 = axes('Position',[.7 .7 .2 .2], 'ButtonDownFcn', @dragObject)
fileName = 'peppers.png';
rgbImage = imread(fileName);
imshow(rgbImage);
% Edit...
set(a1, 'PickableParts', 'all')
% h set as imshow object.
set(h, 'HitTest', 'off')
% Neither of these work either. Neither does scrapping imshow and using
% 'image()'
[ EDIT: Looks like you pretty much figured out what to do already. You should just have to set the axes 'NextPlot','add' (which is the same as hold on), and it should work. ]
To set 'HitTest','off' on an image created with imshow, use the image handle returned from imshow and set it afterwards.
However, for using imshow, there are some axes properties to set when the axes is created, in order to get this working right:
a1 = axes( ...
'Position',[.7 .7 .2 .2], ...
'ButtonDownFcn', @dragObject, ...
'NextPlot','add', ... % set this so the axes ButtonDownFcn doesn't get reset to '' when imshow is called
'PickableParts','all') % set this so the axes ButtonDownFcn still executes on mouse-click, after it's made invisible by imshow
fileName = 'peppers.png';
rgbImage = imread(fileName);
h_im = imshow(rgbImage); % return the handle to the image
set(h_im,'HitTest','off'); % set the image 'HitTest' to 'off'
Aha! You Sir, are an absolute superstar, thank you so much, I was right on the verge of trying build this is C++ and then MEX it. The comments are really helpful as well, thanks.
Thanks again. Have a great day.
You're welcome!
you might be a level 9 but your solution is worhless!
I tried 'HitTest','off' on the command line and got UNRECOGNIZED function???
As demonstrated in the code examples posted, you need
set(HANDLE,'HitTest','off');
for appropriate value of HANDLE

Sign in to comment.

More Answers (0)

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!