ChartContainer is broken?
You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
3 votes
Share a link to this question
3 Comments
Share a link to this comment
Share a link to this comment
Share a link to this comment
Accepted Answer
2 votes
Share a link to this answer
- It causes complicated order-dependency issues between properties, which makes the logic in the code harder to follow and also often breaks saving and loading the chart. If you want to use this approach, you can resolve most of the save issues by making the NumSubPlots and DataAxes and DataLines transient properties.
- It prevents the graphics system from automatically optimizing the performance of your chart. set.Data will run any time the user sets the Data property, but update will only run when MATLAB goes idle or you call drawnow. Imagine a user who is iteratively setting values in the Data property (see the code below). In that example, set.Data will run 10 times, but update will only run once. For that reason, we recommend using update instead (option 2).
- setup should only be used to do setup that will never change in the chart. Because users of the chart can change property values, setup should never rely on user-settable property values (or property values that could be changed indirectly by users, such as NumSubplots).
- update should be used for anything that could change, such as if the user sets a property value.
- update is a "special" method. The graphics system will automatically call update once per graphics update and it will only call update if something has indicated to the system that your chart is out-of-date (such as a property value was set or the figure changed sizes).
- setup is much less "special". It is called automatically from the ChartContainer constructor. If your chart does not have the ConstructOnLoad attribute, it is also called once when your chart is loaded from a FIG-file. Otherwise, there is nothing stopping a power-user from leaving setup empty and putting all the setup code within their own custom constructor, in which case they would have access to anything the user specified.
8 Comments
- setup is much less "special". It is called automatically from the ChartContainer constructor. If your chart does not have the ConstructOnLoad attribute, it is also called once when your chart is loaded from a FIG-file. Otherwise, there is nothing stopping a power-user from leaving setup empty and putting all the setup code within their own custom constructor, in which case they would have access to anything the user specified.
- update is a "special" method. The graphics system will automatically call update once per graphics update and it will only call update if something has indicated to the system that your chart is out-of-date (such as a property value was set or the figure changed sizes).
Share a link to this comment
- ChartContainer can be part of the actual graphics tree. In other words: ChartContainer can be in the Children list of a Figure or Panel. This brings with it an easy way to make your chart be included when you save a FIG-file (without resorting to hacks like UserData or setappdata). This also provides some abstraction (users of a chart don't see the implementation details of the chart).
- ChartContainer hooks into the "Current Axes" mechanism. This allows you to do things like call title('My Data') or call xlim(1:10) without needing to specify your chart as an input argument.
- ChartContainer hooks into the built-in "update" mechanism of the MATLAB graphics system.
- For properties: This applies to all the properties defined on the object itself (as well as some properties, like OuterPosition, defined on base classes) regardless of whether they are private or public and regardless of whether they were set by the object or by something else. This also applies regardless of how you set the property (using obj.Property, using the set function, or if you have a set.<Property> method). We have considered a feature that lets the author of a chart differentiate which properties should mark the object dirty and we may release a feature like this in the future, but for now this applies to all properties defined by the ChartContainer subclass(es).
- Examples of things in the environment that mark an object dirty actually depend on the particular object. Axes, for example, are marked dirty any time the figure size changes. For ChartContainer the list is currently kind of small, it includes: the Parent changed, the Parent of one of the chart ancestors changed, or the theme changed.
- Most promiment and direct is to call drawnow.
- Calling 'pause' will also trigger an update traversal.
- In addition, simply letting MATLAB go idle after running some code will trigger an update traversal (if there is work to be done).
- There are other ways to trigger an update traversal, including querying a property (such as the XLim property on Axes), that we can only answer after we have collected information about all the objects in the axes.
Share a link to this comment
Share a link to this comment
- Is set(obj.DataLines(k), 'XData', t, 'YData', tbl{:,k}) faster than calling obj.DataLines(k).XData = t; obj.DataLines(k).YData = tbl{:,k} or does it prevent calling the drawnow function in between? I remember I made some trials with that but could not draw a clear conclusion. Or is it just personal taste?
- Setting other variables in the setters... This is something that comes across my road every now and then - is it save to supress the warnings using %#ok<MCSUP> in patterns you're showing?
Share a link to this comment
- If you copy all three of those those lines of code together, and paste them together into the command window, and press "enter" once to run all three lines of code, you will trigger just one call to update. That update will occur when MATLAB has gone idle. You will see "done with code" before you see "running update". This is basically equivalent to using set. It does not matter whether the statements are all on a single line or if they are on separate lines.
- If you have both those lines of code in a script or function or class method, and you run that script/function/method, it will queue a call to update that will run when MATLAB goes idle (or you call drawnow). So, once again, you will see "done with code", and then some time later you will see "running update". Note: depending on the circumstances, it may be a while before you see "running update", because MATLAB will wait until all the code has finished executing before running an update (unless you force an update by calling drawnow).
- If you run those lines of code one at a time, you will see "running update" after each property set. Because MATLAB went idle after each property set, and setting the property dirtied the chart, update will run each time. This can happen if you copy/paste each line, and press "enter" once per line. You won't see "running update" after "done with code" because your chart wasn't marked dirty by the disp statement, so update wasn't run again.
- And, of course, if you called either pause or drawnow after each line, you would see "running update" after each property set.
- If Data was restored before DataLines: set.Data will run when DataLines is empty (the default value). If that happens, then width(T) ~= numel(obj.DataLines) will return false (unless the table is empty), which means that NumVarsChanged will be set to true. This means that the code that creates axes and lines will run during the first update of the chart, which is what we want to happen, so we are OK. If the table was empty, NumVarsChanged will be set to false. This means that when update runs for the first time, the code that should be creating the axes and line objects won't run. But, that is OK, because the table is empty and that means we wouldn't create any axes anyway. I think we are OK in this case. However, this all assumes that DataLines is a transient property. If DataLines were not transient, and the table happened to be empty, then DataLines should also be empty, and in that case I think we are still OK.
- If DataLines were not transient, and it was loaded before Data, then I think we are OK, because the code within set.Data is using the loaded value of DataLines to decide whether the chart is out-of-date. However, because DataLines is transient, we know the value will be empty when set.Data runs during the load process, and that should work the way we want it to.
- If NumVarsChanged was not transient, and the value of the Data property was restored before NumVarsChanged, it is theoretically possible that set.Data will set a value for NumVarsChanged, that will be immediately replaced by the loaded value of NumVarsChanged. This could be a problem, but I mitigated this issue by making sure that NumVarsChanged was transient.
- NumVarsChanged and DataLines are both transient, so they won't be restored.
- When set.Data runs, DataLines will be empty (which matches the width of the table), so NumVarsChanged will be false, and depending on how you wrote your code, update may not create the single axes that you expected to be created.
Share a link to this comment
Share a link to this comment
Share a link to this comment
More Answers (0)
Categories
Find more on Entering Commands in Help Center and File Exchange
Products
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)