How can I add a listener to an axe to check everytime the amount of curves is changed. event ChildAdded works, but event ChildRemoved seem to not work.

24 vues (au cours des 30 derniers jours)
Hi all,
I'm creating an app where an user get to load a picture of a graph (like from a scientific text book) and run a script so that he can obtain the data on the picture, i.e. adding a grid and the value of the grid, a value in pixel within the picture transform into a value within the axes of the graph. the user can then "select the position of the curve of interest" in the picture (using ginput) and the program transfer the line thus created into a line with the values as in the picture. (hope I'm being clear). as an example:
you have a picture of a graph showing the evolution of the population of deer in a forest over time. this picture when loaded into matlab would be referenced by a number of pixels. but on those pixels, the user can see that the X-axis is in unit months and the Y-axis in thousand of deer. building a grid at each value of both axis, it is then possible, for example, to put an equivalence between pixel (340, 240) and the value (May 2022/15'500) and the pixel (350,210) to the value (June 2022/12500) (hypothetical value..there has not been a massive death of deer in the forest within May :))
I have all the functions I need to make this app works but I wanted to build it "stupid proof" such that an user cannot mess up the app. one aspect I wanted to ensure was that any deletion of a curve would be traced through all the functions. so that I don't get a mistmatch between the amount of curves seen in the plot in "pixel value", and the amount of data registered in "time/deer" value.
I wanted then to add a listener to the "Children" of the axes so that whenever the amount of children change, the change can be capture by the other functions as well.
however, the property Children of axes is not setObservable. so I cannot put a listener on this.
by browsing internet, I found out that there are "hidden" events in the class matlab.graphics.axis.Axes:
m = ?matlab.graphics.axis.Axes;
e = m.EventList;
among this list, there are two events called "ChildAdded" and "ChildRemoved".
I do manage to make a listener to the "ChildAdded" event, but it seems that the "ChildRemoved" does not work, making my "stupid proof" not usable as the user would still be capable of deleting curves without the code knowing about it.
do you have any idea as to how I could solve this lack of "observability" of events linked with deletion of lines in a axes?
  1 commentaire
Bastien Haemmerli
Bastien Haemmerli le 1 Juin 2023
what I found out as a "work around" is the following:
  • define the HitTest property of each item on the app to "off". then the user cannot select those curve to delete them. this is actually pretty good solution for all the "fix" item on the GUI: UIcontrols,... but for the lines on the axes, it could make sense that the user is capable of deleting some of them, in case he did a mistake for example.
  • create an envelope function to the plot function that in addition would change the UserData of the axes: this would help in registrering every new curves, but would not help when the curves get removed.
  • add functions to delete curve as a UIcontrol on the GUI, with then the callback of this UIcontrol making sure that the deletion is traced all across the app.
but it would be much easier if I could simply listen to the change in Children of the axes in my opinion...

Connectez-vous pour commenter.

Réponse acceptée

Debadipto
Debadipto le 8 Juin 2023
Hi Bastien,
One possible solution to the lack of "observability" of the "ChildRemoved" event in the MATLAB graphics.axis.Axes class could be to manually check for changes in the number of children in the axes at regular intervals using a timer object.
Here is an example of how you could implement this:
1. Create a timer object that calls a callback function every few seconds (depending on how often you want to check for changes in the axes):
t = timer;
t.TimerFcn = @check_axes_children;
t.Period = 5; % Check every 5 seconds
t.ExecutionMode = 'fixedRate';
start(t);
2. In the callback function, check for changes in the number of children of the axes and update a persistent variable that keeps track of the number of children. You can then compare the current number of children to the persistent value to see if any children have been deleted:
function check_axes_children(~, ~)
persistent n_children
ax = gca;
if isempty(n_children)
n_children = numel(ax.Children);
elseif n_children > numel(ax.Children)
% A child has been removed
% Do something here to update the rest of the app with the change
end
n_children = numel(ax.Children);
end
This callback function checks the current number of children in the axes `ax` and compares it to the persistent variable `n_children`, which is initially set to the number of children.
If the current number of children is less than `n_children`, then a child has been removed from the axes and you can handle this event accordingly (e.g. update the rest of the app with the change).
For further information, please refer the following documentation(s):
Regards,
Debadipto Biswas

Plus de réponses (0)

Catégories

En savoir plus sur Interactive Control and Callbacks dans Help Center et File Exchange

Produits


Version

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by