Copy Legend from UIAxes to another UIAxes

81 views (last 30 days)
Jason
Jason on 6 Dec 2025 at 7:45
Commented: Umar about 12 hours ago
Hello,i want to copy a plot on a uiaxes to another uiaxes and can do using the following - but I can't get the legend to copy accross (I want to avoid using the downloadedable copyuiaxes for now)
ax1=app.UIAxes3 % My main axes for plotting
ax1.Children
L1=ax1.Legend % This works
L1s=L1.String{1} % and this
f2=figure; ax2=axes(f2);
new_children=copyobj(ax1.Children,ax2);
makeGraphBlack(app,ax2,'k','w'); % My own function to change appearance (background & grid)
% Copy desired axes properties
ax2.XLim=ax1.XLim; ax2.YLim=ax1.YLim;
ax2.Title.String=ax1.Title.String;
ax2.XLabel.String=ax1.XLabel.String;
ax2.YLabel.String=ax1.YLabel.String;
propsToCopy={'FontSize','Color','GridLineStyle'};
for prop=propsToCopy
set(ax2,prop{1},get(ax1,prop{1}));
end
%Copy Legend
legend(ax2)
ax2.Legend=L1;
legend.TextColor = 'w';
This gives me the error message:
Unrecognized function or variable 'legend'.
Also I notice copyobj doesn't retain the colours of the plots, so I thought adding 'Color' to propsToCopy would do it. Do I have to go the route of finding the line objects of the ax1 children, and then dig down into each of their colors - or is there a quicker way?
Thanks
  1 Comment
Jason
Jason on 6 Dec 2025 at 8:52
Ive also tried this which works to some extent:
lgd=legend(ax2,L1s)
ldg.TextColor=L1.TextColor
lgd.FontSize=L1.FontSize
disp('textColor')
L1.TextColor
lgd.TextColor
For some reason its not changing the TextColor (but is changing the Fontsize)
textColor
ans =
1 1 1
ans =
0 0 0

Sign in to comment.

Answers (1)

Umar
Umar on 6 Dec 2025 at 9:40
Edited: Umar on 6 Dec 2025 at 9:43

Hi @Jason,

I've looked into the legend and color issues you're having when copying plots from UIAxes3 to a new figure, and here's what I found from the MathWorks documentation. The main problem with your legend error is that starting from MATLAB R2014b, legends and colorbars must be copied together with their associated axes as a vector input to copyobj

https://www.mathworks.com/help/matlab/ref/copyobj.html

so instead of trying to assign the legend directly with ax2.Legend=L1, you need to use copyobj([ax1.Children, ax1.Legend], ax2) which copies both the plot children and the legend together in one operation. Your second approach where you created a new legend using lgd=legend(ax2,L1s) was on the right track, but the TextColor issue you're seeing where it shows white then black is likely because MATLAB has automatic property modes that can override manual settings when legend properties inherit from the parent axes

https://www.mathworks.com/help/matlab/ref/matlab.graphics.illustration.legend-properties.html,

so after setting lgd.TextColor=L1.TextColor, try adding a drawnow command to force the graphics system to update immediately, or you might need to explicitly set all the legend's appearance properties including FontSize, Location, and other formatting in one go. Regarding the plot colors not being retained by copyobj, the colors should actually be preserved since they're stored in the line objects themselves rather than as axes properties, so when you added 'Color' to your propsToCopy list, that was actually copying the axes background color rather than the line colors. The line colors are properties of each individual line object in ax1.Children, so if the colors aren't appearing correctly, you can iterate through the children and manually copy them with something like for i=1:length(ax2.Children), ax2.Children(i).Color=ax1.Children(i).Color, end, keeping in mind that copyobj can reverse the order of objects so you might need to flip the indices. The most reliable solution would be to use copyobj([ax1.Children, ax1.Legend], ax2) to handle everything at once, then copy over any additional axes properties you need with your existing loop, and if you're still having issues with the legend appearance, recreate it with legend(ax2, L1.String) and manually copy all the legend properties. For more details on legend properties and text color settings, check out the complete documentation at

https://www.mathworks.com/help/matlab/ref/legend.html and

https://www.mathworks.com/help/matlab/ref/matlab.graphics.illustration.legend.text-properties.html .

Hope this helps!

  6 Comments
Jason
Jason 36 minutes ago
Wow, this is fantastic and very nicely explained too.
I've added a few more things to the Legend part of the resetTosource function
if ~isempty(app.sourceAxes.Legend)
L = app.sourceAxes.Legend
lgd=legend(destAxes, L.String, 'Location', 'best')
lgd.FontSize = L.FontSize;
lgd.TextColor = L.TextColor;
lgd.Box = L.Box;
lgd.Color = L.Color;
lgd
drawnow;
end
But it doesn't pick up the 12.5 fontsize of the source legend.
Any idea why its setting it to 14?
L =
Legend (data1, data2) with properties:
String: {'data1' 'data2'}
Location: 'none'
Orientation: 'vertical'
FontSize: 14 %-----------------DESTINATION---------------
Position: [0.25351 0.66299 0.13855 0.093186]
Units: 'normalized'
Show all properties
lgd =
Legend (data1, data2) with properties:
String: {'data1' 'data2'}
Location: 'best'
Orientation: 'vertical'
FontSize: 12.15 %---------------------SOURCE------------------
Position: [1.8688 2.5233 0.934 0.425]
Units: 'normalized'
Show all properties
lgd =
Legend (data1, data2) with properties:
String: {'data1' 'data2'}
Location: 'best'
Orientation: 'vertical'
FontSize: 14 %---------DESTINATION AFTER FONTSIZE SET --------
Position: [1.8423 2.5033 0.987 0.465]
Units: 'normalized'
Umar
Umar 2 minutes ago

Hi @Jason,

Sorry for the late response. Looking at your output, I can see exactly what's happening.

When you create the legend with ‘Location', 'best’, MATLAB recalculates the FontSize based on the destination axes FontSize (typically 90% of the axes font size). Then when you set ‘lgd.FontSize = L.FontSize’,it's not sticking because the property is still in automatic mode.

According to the MATLAB documentation for legend text properties, the ‘FontSize’ property has a corresponding ‘FontSizeMode’ property that can be either ‘auto' or ‘manual'. When you set FontSize, it should automatically switch FontSizeMode to 'manual', but there appears to be a timing issue when using dot notation immediately after legend creation with location-based positioning. Here's your corrected code using name-value pairs during legend creation as recommended approach:

if ~isempty(app.sourceAxes.Legend)
  L = app.sourceAxes.Legend;
  lgd = legend(destAxes, L.String, 'Location', 'best', 'FontSize', 
  L.FontSize);
  lgd.TextColor = L.TextColor;
  lgd.Box = L.Box;
  lgd.Color = L.Color;
  drawnow;
end

Alternatively, if you prefer setting properties after creation:

if ~isempty(app.sourceAxes.Legend)
  L = app.sourceAxes.Legend;
  lgd = legend(destAxes, L.String, 'Location', 'best');
  set(lgd, 'FontSize', L.FontSize);  % Automatically sets FontSizeMode
   to 'manual'
  lgd.TextColor = L.TextColor;
  lgd.Box = L.Box;
  lgd.Color = L.Color;
  drawnow;
end

The key difference is that setting FontSize as a name-value pair during legend creation (or using the `set` function) ensures that `FontSizeMode` is properly set to `'manual' and your FontSize value will stick.

References

Matlab Legend Text Properties

MATLAB Set Function

Default Text Size in Legends Discussion

Let me know if this resolves the issue or if you run into any other quirks!

Sign in to comment.

Products


Release

R2024b

Community Treasure Hunt

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

Start Hunting!