Get output values from addlistener

A rectangle is drawn in a figure and mooved to a new position. I use addlistener CallBackFunction (@allevents). I get the new (mooved) rectangle data (i.e. xx & yy) but only inside the CallBack function. I cannot extract them (i.e. the xx & yy as in the code below) from the CallBack function to my script for further use. I am new in MatLab; I have searched hours for a similar questions in the site. The answer in https://uk.mathworks.com/matlabcentral/answers/264979-continuous-slider-callback-how-to-get-value-from-addlistener does not seem to work for me. Could you please advise me? Many thanks. My code looks like:
f = figure;
hax = gca;
distpoly = drawrectangle(hax,'LineWidth',1,'Color', 'k');
pathcoord = distpoly.Position;
addlistener(distpoly,'ROIMoved',@allevents);
oldpos = xx; % Error: Unrecognized function or variable 'xx'.
newpos = yy; % Error: Unrecognized function or variable 'yy'.
function [xx, yy] = allevents(src,evt) % the [xx,yy] is not working as output
evname = evt.EventName;
switch(evname)
case{'ROIMoved'}
xx = evt.PreviousPosition; % it works OK here but xx cannot be extracted from the CallBack function
yy = evt.CurrentPosition; % it works OK here but yy cannot be extracted from the CallBack function
disp(['ROI moved previous position: ' mat2str(evt.PreviousPosition)]);
disp(['ROI moved current position: ' mat2str(evt.CurrentPosition)]);
end
disp(xx); % it works OK
disp(yy); % it works OK
end

3 Comments

We can get this straightened out. To guide you in the best direction, it would be helpful to understand how you're going to use these values. Callback functions do not have outputs but it's easy to get the current position directly from the distpoly object. It's also fairly easy to store values to file or within an object property from within a callback. The best option depends on how you are going to use and access these values.
Firstry, I thank you very much for your prompt response. The code I provided is an example of my problem. I intend to use the addlistener and the CallBack in my code as an intention the user to have the flexibility to make an initial ROI (e.g. rectangle, any shape) in a figure and then to re-arrange its shape, position, etc. The new ROI data would be used as "coordinates" to calculate other parameters of my code (in sebveral parts of it), e.g. area, position, ROI pixels, etc. I think not to store the ROI data in a file from from the CallBack for code timing purposes (the code user may re-arrange the ROI many times). Other proposals on this are mostly approciated. Also, it would be great if you could indicate specific sources (links) for further reading (other than MatLab documentation). I thank you very much for your timing and consideration.
Some callback functions have outputs, but most do not. zoom / pan constraint callbacks have outputs, and data cursor mode UpdateFcn have callbacks, and a few others.

Sign in to comment.

 Accepted Answer

Adam Danz
Adam Danz on 16 Jan 2023
Edited: Adam Danz on 18 Jan 2023
> The new ROI data would be used as "coordinates" to calculate other parameters of my code
There's no need for a listener to access the new ROI data. You can get that directly from the ROI object.
h = drawrectangle(hax, ...);
Rectangle with properties:
Position: [0.1438 0.43954 0.2533 0.47059]
RotationAngle: 0
AspectRatio: 1.8578
Label: ''
Color: [0 0 0]
Parent: [1×1 Axes]
Visible: on
Selected: 1
Show all properties
The h.Position property gives you the ROI's current position in the form of [x,y,w,h] where (x,y) is the lower left corner and (w,h) are the width and height which can be used to compute all 4 corners.
As for the additional resource request, MATLAB's documentation has always been more than sufficient for me. Other than that, I just search google when needed.
Show ROI Moving feedback
This demo uses a listener that responds to a MovingROI event. It update the text label showing the lower left coordinate of the rectangle and updates the xline/yline crosshairs.
fig = figure;
ax = gca;
h = drawrectangle(ax,'LineWidth',1,'Color', 'k');
txt = text(nan,nan,'','VerticalAlignment','top');
xl = xline(nan);
yl = yline(nan);
MovingROIFcn(h,[],txt,xl,yl) % initialize the text obj and cross hairs
% Freeze axis limits
ax.XLimMode = 'manual';
ax.YLimMode = 'manual';
addlistener(h,'MovingROI',@(src,evt)MovingROIFcn(src,evt,txt,xl,yl));
function MovingROIFcn(src,~,txt,xl,yl)
xy = src.Position(1:2);
txt.Position(1:2) = xy;
txt.String = sprintf('(%.3f, %.3f)', xy);
xl.Value = xy(1);
yl.Value = xy(2);
end

5 Comments

I thank you for your response once again. There are many options to do in the code, as the one you proposed which is the simplest and easiest. However, in my understanding, “listener” could provide a “real time” interaction with a user, while the CallBack output, in "real time", could make the code effective and interesting. Anyway, I do not wish to bother you anymore on this and I deeply appreciate your time and efforts on my request..
Adam Danz
Adam Danz on 18 Jan 2023
Edited: Adam Danz on 18 Jan 2023
Indeed, a callback function could be used to create realtime feedback to the user. If you describe how you'd like to use a callback function with an ROI object I would be happy to offer additional guidance.
Seizing your willingness to further assist, I would like to say that the code I am trying on is something like "AutoCAD". The user could draw a shape, ROI (e.g. room, sofa, table, etc) and when moving/changing the ROI to see in a separate window how some calculated parameters (dimensions, area, posistion, distances between different objects etc) are changing in real time, as the ROI changes. Something like that. Before deciding on the approach of the code, it is crucial fro me to check if the listener and the CallBack are appropriate to support my code. Many thanks again.
In that case, you could update a text window from within the listener. I'll update my answer to share a demo.
This is what I was looking for. I thank you so much. I really appreciate your time and willingness to help.

Sign in to comment.

More Answers (1)

For most graphic objects and behaviors, you have code that configures a callback, and then the configuration code keeps running and returns when the configuration finishes. The configuration code does not (usually) wait for user interaction, just configures what will happen when the interaction is detected. When the interaction does happen and the callback is invoked, there is nothing to return any value to, as the configuration routine has already finished.
If you need the results of a callback then you need to invoke a function that uses uiwait() or waitfor() to configure the callback, and then sit around waiting for the callback to be invoked, after which you extract the results from whatever variables or objects, turn off the callback, and continue. See for example the code for inputdlg() which creates a figure and text edit area and waits for events, extracts the contents of the text edit object, destroys everything and returns.

1 Comment

Thank you for your comments, advice and time spend. I appreciate it.

Sign in to comment.

Products

Release

R2019b

Community Treasure Hunt

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

Start Hunting!