Clear Filters
Clear Filters

Prevent Matlab from updating the legend when saving a figure

47 views (last 30 days)
I have a figure with a tiled layout and some plots which - because they are partly related - I don't want to give them all their own legend entry, but rather summarise several plots with one entry. I do this by subsequently changing the legend entries to display several line types, like in this example:
leg = legend([plot1, plot2], {'Plot1', 'Plot2'});
drawnow();
% Update legend
hLegendEntryTop = leg.EntryContainer.NodeChildren(end); % top row of legend
iconSet = hLegendEntryTop.Icon.Transform.Children.Children; % array of icons
% Move primary line up
iconSet(1).VertexData(2,1) = 0.65;
iconSet(1).VertexData(2,2) = 0.65;
% Create a new line
iconSet(2) = copy(iconSet(1)); % copy the object
iconSet(2) = iconSet(1).Parent; % set the parent, adding to the legend's icon draw set
% Move primary line down
iconSet(2).VertexData(2,1) = 0.35;
iconSet(2).VertexData(2,2) = 0.35;
iconSet(2).LineStyle = 'dashed';
...... % Do the same with other plot lines
saveas(gcf,'figure','epsc')
Interestingly, it works when exporting as PNG, but not when exporting as eps or pdf (vector graphics). The image is then updated and all additional lines inserted disappear again. I have absolutely no idea how I can prevent Matlab from updating the legend again when saving.
  1 Comment
dpb
dpb on 13 Jul 2024 at 14:40
Edited: dpb on 13 Jul 2024 at 20:55
leg = legend([plot1, plot2], {'Plot1', 'Plot2'});
Unrecognized function or variable 'plot1'.
drawnow();
% Update legend
hLegendEntryTop = leg.EntryContainer.NodeChildren(end); % top row of legend
iconSet = hLegendEntryTop.Icon.Transform.Children.Children; % array of icons
% Move primary line up
iconSet(1).VertexData(2,1) = 0.65;
iconSet(1).VertexData(2,2) = 0.65;
% Create a new line
iconSet(2) = copy(iconSet(1)); % copy the object
iconSet(2) = iconSet(1).Parent; % set the parent, adding to the legend's icon draw set
% Move primary line down
iconSet(2).VertexData(2,1) = 0.35;
iconSet(2).VertexData(2,2) = 0.35;
iconSet(2).LineStyle = 'dashed';
...... % Do the same with other plot lines
saveas(gcf,'figure','epsc')
  1. Format your code
  2. Provide complete Minimum Working Example
Such shenanigans are generally more successfully obtained by creating dummy lines of the desired characteristcs and then using the legend() function for those and not displaying the legends for the other lines at all.
But we need MWE code and an illustration of what effect(s) you're trying to achieve would never hurt...

Sign in to comment.

Answers (1)

Benjamin Kraus
Benjamin Kraus on 15 Jul 2024 at 18:16
By using the EntryContainer and NodeChildren properties, you are accessing the undocumented internal implementation details of the Legend. One aspect of being undocumented internal implementation details is that MATLAB is free to change the values of those properties whenever it wants, so this approach is not going to be reliable, and could break any time.
  • When you export to a PNG you are lucky that MATLAB doesn't redraw the scene, so it doesn't update those properties.
  • But, when you export to a PDF or EPS, MATLAB needs to change the internal layout and rendering a bit, so it does a graphics update, and during that graphics update all those properties you set are going to be restored to their original values.
The recommended way to create entries in the legend that don't match items you can see are you create entries with NaN data.
Something like this:
hold on
solidLines = plot(magic(4));
dashedLines = plot(magic(4)+2,'--');
invisibleSolid = plot(NaN, 'k', 'DisplayName', 'Solid lines');
invisibleDashed = plot(NaN, 'k--', 'DisplayName', 'Dashed lines');
legend([invisibleSolid invisibleDashed])
  1 Comment
Benjamin Kraus
Benjamin Kraus on 15 Jul 2024 at 18:21
Edited: Benjamin Kraus on 15 Jul 2024 at 18:24
You can still use this approach if you have several axes in a tiledlayout.
t = tiledlayout(2,2);
y = [sin(1:10)' cos(1:10)'];
for ii = 1:4
ax(ii) = nexttile(t);
p(ii*2-[1 0]) = plot(y);
p(ii*2).LineStyle = '--';
end
h = legend(ax(ii),p(1:2));
h.Layout.Tile = 'east';

Sign in to comment.

Tags

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!