addlistener for drawrectangle to trigger when the rectangle is first drawn

22 views (last 30 days)
I want the user of my code to draw a rectangle in a plot, with:
roi = drawrectangle();
I understand how to set up a listener that gets triggered whenever the drawn rectangle gets moved/resized:
addlistener(roi,'ROIMoved', @roi_listener);
... but how do I do something similar when the rectangle is first drawn? This does not work:
addlistener(roi,'DrawingFinished', @roi_listener);
  2 Comments
Adam Danz
Adam Danz on 8 Jun 2021
You'll have to set up a listener that monitors new objects added to the axes and determines if they are rectangles added by the drawrectangle function. That's why my answer does. It then removes the listener after the first rectangle is added (you can remove that section if you'd like).
Michal Merman
Michal Merman on 31 May 2023
Nice and elegant :)
However, this still leaves open the question how can DrawingFinished event be used?
I'm having the same issue, I'd like something to happen each time I draw a rectangle on the image - but I can't define the listener before object creation.
Would creating a custom class based on Rectangle do that?
Thanks :)

Sign in to comment.

Answers (1)

Adam Danz
Adam Danz on 4 Jun 2021
Edited: Adam Danz on 9 Jun 2021
How to add listener that responds to the first time drawrectangle is called
For instructions on how to implement this in AppDesigner, see my comment below.
Create figure & axes
A random scatter plot is also added for demo purposes only.
fig = figure();
ax = axes(fig);
plot(ax, rand(1,20),'o')
Create listener
  • The listener will respond when objects are added to the axes but contains a condition to check for image rectangle objects.
  • The listener is stored within the axes userdata. Alternatively, you could use set/getappdata.
ax.UserData.Listener = addlistener(ax,'ChildAdded',@drawRectDetectionFcn);
Call drawrectangle
roi = drawrectangle(ax)
Listener callback function (Version 1)
The callback function performs the following tasks
  • Extract all children handles from axes.
  • Looks for "images.roi.Rectangle" objects.
  • If none are found the function returns without doing anything.
  • If a images.roi.Rectangle object is detected, the function will perform whatever action you want (fill in the code) and at the end, it will remove/disable the listener since you only want this to trigger when the first rectangle is added.
The listener can be either disabled (with the option to re-enable it again) or it can be permanently deleted. Both commands are included - you can decide which is best for your needs.
Important:, the listener will trigger when the object is added and the image rectangle object is added when drawrectangle is called before the user interactively draws the rectangle. Nevertheless, you can change properties of the rectangle such as color, for example, before the rectangle is drawn.
function drawRectDetectionFcn(ax,~)
% Evoked by listener when children are added to the axes in ax.
% Detects the presence of an images.roi.Rectangle object created
% by drawrectangle() and performs [SOME ACTION]. After the first
% rectangle obj is detected, the listener is removed.
axChil = ax.Children;
chilClass = arrayfun(@(h){class(h)},axChil);
isRect = any(strcmpi(chilClass, 'images.roi.Rectangle'));
if isRect
%
%
% DO YOUR STUFF HERE
%
%
% Remove|Disable listener after the first rectangle is added.
delete(ax.UserData.Listener) % Permanently delete listener
% ax.UserData.Listener.Enabled = false; % Disable listener
end
end
Listener callback function (Version 2)
Update: This version works with Matlab Online but not in a local installation of Matlab.
Use this version of the callback function if you need the listener to respond after the first rectangle is draw. Unlike the first version, the condition requires that the position property of the rectangle is not empty. The position property is initially empty while waiting for the user to draw the rectangle and is filled it after the drawing is complete.
function drawRectDetectionFcn(ax,~)
% Evoked by listener when children are added to the axes in ax.
% Detects the presence of a drawn images.roi.Rectangle object created
% by drawrectangle() and performs [SOME ACTION]. After the first
% rectangle obj is detected, the listener is removed.
axChil = ax.Children;
chilClass = arrayfun(@(h){class(h)},axChil);
isRect = strcmpi(chilClass, 'images.roi.Rectangle');
if any(isRect) && ~isempty(axChil(find(isRect,1)).Position)
%
%
% DO YOUR STUFF HERE
%
%
% Remove listener after first rectangle is added.
delete(ax.UserData.Listener)
%ax.UserData.Listener.Enabled = false;
end
  8 Comments
David Aronstein
David Aronstein on 11 Jun 2021
I'm not sure I understand.
In my thinking of what I am trying to do, the whole problem is that calling drawrectangle without arguments (so it waits for the user to use the mouse to draw the rectangle) and then actually drawing that rectangle are separate events, and I want the program to respond immediately to the latter, not the former.
I could, instead, call drawrectangle with a 'Position' argument, so the rectangle gets drawn immediately, but then I just use a listener to trigger when it is moved. That's ok but seems a bit inelegant.
Adam Danz
Adam Danz on 11 Jun 2021
The question is, what triggers/calls drawrectangle? Is that part of the code or does the user merely enter it in the command window any time they want?

Sign in to comment.

Categories

Find more on Line Plots in Help Center and File Exchange

Products


Release

R2020a

Community Treasure Hunt

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

Start Hunting!