Multiple custom graphics object inheriting from ChartContainer

I am trying to write a custom chart (or graphical object, rather), and I would like to plot several of them in a single figure. I am following this guide, but I keep getting:
Error using matlab.graphics.chartcontainer.ChartContainer
Adding TestChart to axes is not supported. Turn hold off.
In my custom class I am combining a line and a surface, but this a minimal class works as an example:
classdef TestChart < matlab.graphics.chartcontainer.ChartContainer
properties (Access = private, Transient, NonCopyable)
% Chart axes.
HandleLine(1,1) % Handle of the line plot
end
properties
Axes
XData double {mustBeReal}
YData double {mustBeReal}
ZData double {mustBeReal}
end
methods (Access = protected)
function setup(this)
this.Axes = getAxes(this);
% Create line handle
this.HandleLine = plot3(this.Axes, NaN, NaN, NaN, '-o');
end
function update(this)
this.HandleLine.XData = this.XData;
this.HandleLine.YData = this.YData;
this.HandleLine.ZData = this.ZData;
end
end
And then, if I try creating two of them:
a = TestChart('XData', [0 0], 'YData', [0 0], 'ZData', [1 2]);
b = TestChart('XData', [0 0], 'YData', [0 0], 'ZData', [5 8]);
I get the error saying "Adding TestChart to axes is not supported. Turn hold off.".
Is it possible to create custom graphics object that can be plotted several times in the same axex ?
Thanks in advance!

 Accepted Answer

I can't reproduce this issue, but a couple things to keep in mind:
  1. Subclasses of ChartContainer are children of UI containers (like Figures, Panels, etc.). They are not children of axes (they are parents of axes). So, you can't have any charts in the axes, much less two or more.
  2. When you create a ChartContainer, it sets itself as the CurrentAxes (or gca).
  3. The default ChartContainer constructor will create a chart that replaces the current axes or chart (the thing returned by gca). So, if you call TestChart twice, the second one will replace the first one.
There are two workarounds to bullet 3:
The first is to create an axes in between the two calls:
a = TestChart('XData', [0 0], 'YData', [0 0], 'ZData', [1 2]);
axes % Create a new CurrentAxes
b = TestChart('XData', [0 0], 'YData', [0 0], 'ZData', [5 8]); % Will cause the axes to be deleted.
The second is to specify a position when you call the second chart:
a = TestChart('XData', [0 0], 'YData', [0 0], 'ZData', [1 2],'OuterPosition',[0 0 0.5 1]);
b = TestChart('XData', [0 0], 'YData', [0 0], 'ZData', [5 8],'OuterPosition',[0.5 0 0.5 1]);
The theory behind this behavior:
  • The default behavior is to replace the current chart or axes. This to aid in command-line noodling. Without this behavior, every time you called the command, you would get a new chart that overlaps the old chart. You (probably) wouldn't see the old chart, but it would still be there.
  • However, if you've specified a position, then you are more likely to be creating multiple charts and positioning them so they don't overlap. This will disable the "automatically replace the current chart/axes" behavior.

5 Comments

Hi,
Well, in version 2023a I still get the same message when running the example code I provided:
Error using matlab.graphics.chartcontainer.ChartContainer
Adding TestChart to axes is not supported. Turn hold off.
Anyway, I am still interested in this problem. My aim was to create a custom graphical object, and my issue is that it disappeared when the handle was cleared. I solved the problem by adding the handle to the figure's appdata, so now my object is persistent.
If there's a better way to do it, I'd love to know!
@Claudio: I copy/pasted your code from above, added the missing end statement to make it valid code, and tried to reproduce that error. The only way I found to reproduce that error using the code above was if I did this:
axes
hold on
a = TestChart('XData', [0 0], 'YData', [0 0], 'ZData', [1 2]);
Getting an error in that case is expected, as you've enabled hold on the existing axes, which MATLAB interprets as you trying to add a TestChart as a child of your axes, which isn't supported. Calling TestChart will normally replace your axes, but because hold is enabled, MATLAB is throwing an error instead.
I'm very curious about your description saying "it disappeared when the handle was cleared. I solved the problem by adding the handle to the figure's appdata."
That definitely should not happen. When your chart is visible, it will be stored in the Chilren property of the container it is in (usually the Children property of the figure). That should be enough to keep the object alive.
Are you able to see that issue with the code above, or are you doing something more complicated? If not the code above, I'd be interested to see a minimal example that can reproduce the problem you are seeing.
Also: Are you using the Live Editor? If so, do you see different results when running code in the Live Editor versus running things at the command line?
Well, to be honest this post is from 3 years ago, and now I am not able to reproduce the issue of the graphics objects disappearing...
But I do understand your explanation of ChartContainer, I misunderstood its use !
Hello Benjamin,
I came across this behaviour in R2024a.
The following code is an extension of the SmoothPlot example from doc matlab.graphics.chartcontainer.ChartContainer.
f = figure;
ax = axes('Parent',f);
x = 1:1:100;
y = 10*sin(x./5) + 8*sin(10.*x + 0.5);
disp(ax)
c = SmoothPlot('XData',x,'YData',y...
,'Parent',f...
... ,'Position',[0 0 1 1]...
);
disp(ax)
As you suggest, if 'Position' is not specified then SmoothPlot seems to delete the pre-existing axes object.
This is very unexpected behavour that I have not been able to find documented elsewhere. May I suggest that this behaviour be emphasized in the official documentation?
@Fred Dilkes: I have sent that feedback to our documentation writer.

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2021a

Community Treasure Hunt

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

Start Hunting!