MATLAB Answers

Dan
0

Can you detect when a title is added to a plot?

Asked by Dan
on 27 Feb 2019
Latest activity Commented on by Dan
on 28 Feb 2019
I have a GUI where a single figure has multiple pannels. Graphs can be added to these panels at any unknown time by a user. I want to populate a popup menu with the titles of graphs (axes) as they are added to these panels by the user. User population is to work the same as adding a plot to a standard figure in that after creating the figure, the code really has no idea at what point the user will add the plot and the title so there is no post add title point at which to pull the title. It would instead need to be able to react to the title being added. I have tried manualy creating a blank axes on the panel for which the user will plot to next so that the next plot is directed there and attached a propertly listerer to the string property of the title object of the axes. This should work except that it doesnt due to new plots to an existing axes result in the old axes title being deleted in the background with no clear way to find the handle to the new title. Any ideas on a good way to do this?

  7 Comments

I should further add that the point of my GUI is to completely replicated the functions of a standard matlab figure but instead do it with multiple panels inside a single figure such that each panel is to behave as a standalone matlab figure would (which I have working).
Ummm, it seems unlikely that you have it fully working. Standard MATLAB figures are not just graphics containers: figures also have behavior associated. For example, bode() forces the behaviour for the figure to change, and it does so in a way that is not compatible with having multiple panels each with different behaviour.
There is a way to do it in MATLAB, using routines that have little documentation, but you would have mentioned those if you were using them, as they have a bunch of complications.
Im sure it is quite likely there are some unique cases that I have not completely handled, but for the case of bode() I would say that it functions just fine from what I am aware of and have tested with the one exception being that the title finding methods described in this thread wont work for it (which is fine, I have a default name in the popup with just the number of which the graph was added to the figure ie Graph 12). Features I can think of for this which are typically figure dependent include the Data Cursor function. Typically defining your own data tip function is figure dependent and thus multiple graphs would cause issues but from just now testing it works just fine with bode() even with multiple axes on multiple panels. This does leave me a little curious as to how the data cursor function on this graph is set up. I even tested moving the panel containing a bode plot to a new figure and this still seemed to work which I did not expect. Something I will have to look into as I would like to set up Data Cursors like this in some other code of mine.
I would be curious to hear what other aspects of bode() or other functions you dont think would work as I would like to test but as far as I can tell the panels in the figures work just fine for operation of the plots.
I should also note that no undocumented matlab was used for this part of the code, although I do use a few background java aspects for unrelated parts of the code.

Sign in to comment.

2 Answers

Answer by Dan
on 27 Feb 2019
Edited by Dan
on 28 Feb 2019
 Accepted Answer

I was able to figure out a good method for detecting the axes being reset which could then be used to create a new listener for the title. An example is as follows:
ax = axes;
TitleAddFcn = @(~,~)disp('Title changed');
addlistener(ax.Title,'String','PostSet',TitleAddFcn);
addlistener(ax,'Reset',@(src,~)... addlistener(src.Title,'String','PostSet',TitleAddFcn));
surf(peaks)
title('Hello World')
It turns out that an axes has a reset event that will notify when cla reset is called. cla reset is called by the newplot function whenever the axes NextPlot property is set to the default value of replace. newplot is called on all new plot calls in matlab. So everytime the function plot or other plotting functions are run newplot is called and if the NextPlot property is the default then cla reset will be called triggering the reset event for the axes. This event was found by doing the following:
mc = metaclass(axes); {mc.EventList.Name}
So now with this setup the listener is set to the axes title for the title change and a listener is set to determine if a reset of the axes is performed. If so a new axes title listner is created. It should be noted that addlistener is supposed to create listernes which are tied to their event object and thus should be deleted when the object is deleted. In our case if the axes is reset the original title object is deleted and the original title change listener should also be deleted. If the axes is deleted then both the reset listener and the current title change listener should be deleted so these should not need to be tracked to ensure there are no persistant listeners to deleted objects (this is atleast how I interpret it to work, if I am wrong please let me know).

  0 Comments

Sign in to comment.


Answer by Sean de Wolski
on 27 Feb 2019

If the axes already exists, this seems to work
ax = axes
addlistener(ax.Title,'String','PostSet',@(~, ~)disp('hi'))
title('Hello World')
Now just change the listener callback to fire an update of your listbox.

  7 Comments

@Jan: As best I can think about it, that is the best way to do it as the popup exists and is displayed potentially before all graphs have been added. Adding graphs is at the will of the user the same as they could make a new figure at any point and start plotting to it. A better solution could be potentially finding a background java listener that only fires when the popupmenu is clicked/opened.
@Dan: I've done equivalent things in the Matlab level by creating an 'Enable'='inactive' element and let its ButtonDownFcn (not the Callback) trigger the automatic collection of data. Then instead of a popup menu I show a UIContextMenu at the same position, because I can set its Visible status dynamically to let it appear as if it was an activated popup menu. Not nice to write, but looks fine and I have all functionality, where it is needed. The user can do, whatever he wants, because the pseudo-popup keeps the power of finding, what it is needed.
Of course I do like the idea of letting new objects send a message which allows to identify them. But as long as Matlab is not completely object oriented and the plot command is inherited from the current figure automatically, such that you can define figure depended modifications directly, I prefer the active collection instead of a message passing.
@Jan: Not a bad idea. I could see that working pretty well. I have been shying away from this aproach (the menu click callback) though due to the popupmenu being hidden at points and being replaced with an undocumented style jcombobox and that I am a bit worried about checking the titles everytime the user interacts with the GUI as it would slow down the GUI as far as the user sees. As I see it I have the option of slowing down a bit at build via the listener methods or slowing down on each user interaction via button callbacks. One things I will need to test however is the slowdown of 2 listeners per axes in the figure. In the case where I have hundreds (or even thousands) of axes in the figure perhaps this might start causing issues. Would be nice if it were possible to just have a single listerner for a call to the title() fuction.

Sign in to comment.