how to merge two legend in one?
64 views (last 30 days)
Show older comments
Arash Hajisharifi
on 7 Mar 2020
Hello every one,
i have three plots and i want to have just one legend for plot p1 and p2 ,for example for the following code:
x=0:0.25:2*pi;
y=sin(x);
p1=plot(x,y);
hold on
p2=plot(x,y,'o','MarkerSize',12,'MarkerFaceColor','b','MarkerEdgeColor','b');
p3=plot(x+0.02,y+0.02,'o','MarkerSize',4,'MarkerFaceColor','w','MarkerEdgeColor','w');
as you see i have merged two markers(a big blue circle and a small white circle ) and i want two show these two circles together as same legend.is there any way to do it?

3 Comments
dpb
on 8 Mar 2020
I tried
hL(2)=plot(x+dxy,y+dxy,'or','MarkerSize',4);
also and thought kinda' cute...
Accepted Answer
Walter Roberson
on 7 Mar 2020
Yes, there is a way to do it.
[h, icons] = legend([p2, p3], {'whatever the legend should say', 'unused'});
%p2_text = icons(1);
p3_text = icons(2);
p2_line = icons(3);
%p2_marker = icons(4);
p3_line = icons(5);
p3_marker = icons(6);
p2_line.Color = p1.Color;
p2_line.LineStyle = p1.LineStyle; %it is missing the solid line of p1
p3_text.Visible = 'off'; %turn off what you do not need
p3_line.Visible = 'off';
p3_marker.XData = p2_marker.XData + 0.02; %move the small white circle
p3_marker.YData = p2_marker.YData + 0.02;
This is a bit clunky.
You have to use a backwards compatibility of legend() that will probably go away and might not work for uifigures. You must have two or more outputs on the legend() call: the backwards compatibility is triggered by that. If you only have one output on the legend call, then it does not create the objects that you need to have created.
You cannot just pass a single graphics object as the first parameter to legend and add-on the additional graphics within the legend, as you are not permitted to add additional graphics objects inside a legend. Instead you have to create as many graphics objects as you need at the start, and then turn off the legend portions of them that you do not need. But you can move the objects that are already inside the legend.
2 Comments
dpb
on 7 Mar 2020
Edited: dpb
on 7 Mar 2020
"have to use a backwards compatibility of legend() that will probably go away..."
Indeed, legend was klunky before and now, while TMW has added some features, their recent penchant for hiding needed/useful properties from the user and not only making them invisible but to actually make the object almost totally opaque is a real kick in the teeth for such user niceties.
Dunno that users have the power to change the mindset that seems to have developed that we are children that must be protected from ourselves, but it is surely disheartening.
A quick look-thru using Yair's undocumented function makes it appear that even by getting to what is exposed but hidden isn't enough to be able to get to the actual objects; TMW has appears to have completely made them inaccessible.
I guess I now recall having been thru the exercise earlier that one cannot even use those hidden properties to get the children of the axes buried in the new legend object. If TMW does choose to actually remove the backwards compatibility feature, one will be hosed entirely other than by completely reinventing the wheel.
"Ease of use and rapid development" as long as willing to live with what is deemed allowable...
More Answers (3)
Nathan Miller
on 19 Oct 2021
Edited: Walter Roberson
on 13 May 2023
If you dig in deep enough you absolutely can customize the legend icons to whatever you want programatically, but it's quite messy and 'undocumented'.
I came up with my solution below after looking through Yair's https://undocumentedmatlab.com/blog_old/plot-legend-customization and thinking outside the box a bit with a colleague. The key was doing the copy of the node object to create a new Marker primitive and then updating the Parent property that loads it into the legend handle to be drawn.
% Plot OP's code
figure; hold all; % new fig, enable hold/add
x=0:0.25:2*pi;
y=sin(x);
hL(1)=plot(x,y,'o-','MarkerSize',12,'MarkerFaceColor','b','MarkerEdgeColor','b');
hL(2)=plot(x+0.02,y+0.02,'o','MarkerSize',4,'MarkerFaceColor','w','MarkerEdgeColor','w');
% Add legend for the first/main plot handle
hLegend = legend(hL(1),'location','best');
drawnow(); % have to render the internal nodes before accessing them
% Extract legend nodes/primitives
hLegendEntry = hLegend.EntryContainer.NodeChildren(1); % first/bottom row of legend
iconSet = hLegendEntry.Icon.Transform.Children.Children; % array of first/bottom row's icons (marker+line)
% Create a new icon marker to add to the icon set
newLegendIcon = copy(iconSet(1)); % copy the object (or look into making a matlab.graphics.primitive.world.Marker)
newLegendIcon.get % list all properties
newLegendIcon.Parent = iconSet(1).Parent; % set the parent, adding to the legend's icon draw set
% Mess with the new icon's properties to show how you want
newLegendIcon.FaceColorData = uint8([255;255;255;255]); % rgba uint8
newLegendIcon.VertexData(1) = 0.53; % [0-1] within the icon's boundaries (not the +0.02)
newLegendIcon.VertexData(2) = 0.65; % [0-1] within the icon's boundaries (not the +0.02)
newLegendIcon.Size = 4; % a little different from MarkerSize it seems
Output image if the auto-run figure from the above code doesn't generate correctly:

Bonus extra figure/example showing how you can separate the icon markers to show multiple of them on the same line:

4 Comments
Jakub
on 25 Mar 2025
I have used your solution and it worked well until I wanted to save the plot as a picture. Regardless of the picture format (.eps or .png...), Matlab has overridden the legend formating back to the standard one while saving the plot.
I have no clue why.
Walter Roberson
on 25 Mar 2025
It depends on which method you used to save the plot as a picture.
Functions such as print() and exportgraphics() build internal copies of figures -- copies with the proper page size and centering implemented. The process of building internal copies of figures involves rerunning the legend() command, which leads to the legend being re-rendered with its default properties.
This problem should not occur if you use getframe ... but that might not be high-enough resolution for your purposes.
Hakan Caldag
on 28 Mar 2023
Edited: Hakan Caldag
on 7 Nov 2023
For anyone who is happy to keep the legend somewhere outside the axes, I ended up with another solution that looks simpler to me: Copying the axes object to have a new one right on top, having two legends for each and setting the top legend color to 'none' so it becomes transparent and both icons become visible:
x=0:0.25:2*pi;
y=sin(x);
subplot(121);
p1=plot(x,y);
hold on
p2=plot(x,y,'o','MarkerSize',12,'MarkerFaceColor','b','MarkerEdgeColor','b');
p3=plot(x+0.02,y+0.02,'o','MarkerSize',4,'MarkerFaceColor','w','MarkerEdgeColor','w');
legend('','Anything here','Position',[0.6 0.6 0.1 0.1])
axhand=gca; %axes handle
duplicateplot=copyobj(axhand,1); % the duplicate
axes(duplicateplot);
% Removing the additional labels/ticks of the second axes object
xticks([]);yticks([]);xlabel('');ylabel('');
legend('','',' ','Position',[0.52 0.6036 0.135 0.1],'Color','none','EdgeColor','none')
% Setting the colors to none is what makes the icons overlap
% Adjust the position any way you would like here, I tried to match the
% shape in the plot.
% Notice that the ' ' label is set for the plot object with the white icons
0 Comments
Jonas
on 18 Jun 2025
Hi,
I've managed to use this methodology to edit some legend entries (using Matlab 2024a), but I'm facing some problems.
For one, when I export to pdf using the function in the window, under File->Export setup (which I do because it generally produces better results for my figures), the first/bottom entry, a line, is overwritten. I have edited the entry for a patch object, which does not get overwritten. I've tried editing other entries after editing the line, making sure that the line objects are deleted, but it still happens. Not sure what's going on here.
I also have error bars (without a line) in the figure. This method seems completely incompatible with error bars, as the 'iconSet' object is an empty graphics placeholder. I've been looking around seemingly everywhere top-down from the legend object itself, but I can't find the actual icon that's being rendered.
Any idea how to deal with these issues?
0 Comments
See Also
Categories
Find more on Legend in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
