- Format your code
- Provide complete Minimum Working Example
Prevent Matlab from updating the legend when saving a figure
16 次查看(过去 30 天)
显示 更早的评论
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 个评论
dpb
2024-7-13
编辑:dpb
2024-7-13
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')
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...
回答(1 个)
Benjamin Kraus
2024-7-15
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 个评论
Benjamin Kraus
2024-7-15
编辑:Benjamin Kraus
2024-7-15
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';
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Legend 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!