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

 採用された回答

Voss
Voss 2022 年 6 月 22 日

0 投票

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 件のコメント

Michael Vinsome
Michael Vinsome 2022 年 6 月 22 日
編集済み: Michael Vinsome 2022 年 6 月 22 日
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()'
Voss
Voss 2022 年 6 月 22 日
編集済み: Voss 2022 年 6 月 22 日
[ 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'
Michael Vinsome
Michael Vinsome 2022 年 6 月 22 日
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.
Voss
Voss 2022 年 6 月 22 日
You're welcome!
Mike McCullough
Mike McCullough 2024 年 2 月 25 日
you might be a level 9 but your solution is worhless!
I tried 'HitTest','off' on the command line and got UNRECOGNIZED function???
Walter Roberson
Walter Roberson 2024 年 2 月 25 日
As demonstrated in the code examples posted, you need
set(HANDLE,'HitTest','off');
for appropriate value of HANDLE

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

その他の回答 (0 件)

カテゴリ

ヘルプ センター および File ExchangeInteractive Control and Callbacks についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by