Change marker size in legends of already plotted figures
29 次查看(过去 30 天)
显示 更早的评论
Hi everyone,
I do not know why but whenever I save some plots in .fig format from Matlab, the size of the markers of the legend is always changed. That means that, if I open again the .fig file in Matlab, the size of the marker is just set to a default (tiny) size.
I know how to change the marker size in plotting phase, but I do not know how to access it again in already plotted figures.
I tried accessing the handle of the legend with
hLegend = findobj(gcf, 'Type', 'Legend')
and then trying accessing the children of type 'line' to then change the 'Markersize' (as explained here https://stackoverflow.com/questions/28741747/change-the-symbols-size-in-matlab-legend)
ch = findobj(get(hLegend,'children'), 'type', 'line');
but I fail in doing this as there is no this kind of 'Children'.
Any suggestion please?
Thanks and best regards
0 个评论
回答(3 个)
Elizabeth Case
2021-8-19
编辑:Elizabeth Case
2021-8-19
I'm using Matlab 2021a. My case use is a bit different than most here but thinking this might prove useful to someone. I am plotting data in a loop, and want the size of the marker in the legend to match the markersize on the scatter plot. I only wanted certain entries to show up in the legend to avoid repetition (in this case, markersize is determined by year).
Note that this does throw warnings, but still seems to work.
Most relevant code for setting legend marker size is marked by %------> <------%
%create data structure -- 3 measurements at 3 locations over multiple years
x = linspace(1,10,12);
y = linspace(0,1,12);
z = linspace(-4,0,12);
names = ['a';'b';'c';'a';'b';'a';'b';'a';'b';'c';'a';'b']; %data
years = [1990,1990,1990,1992,1992,1995,1995,2000,2000,2000,2005,2005]; %data
for i = 1:length(x)
struct(i).x= x(i);
struct(i).y= y(i);
struct(i).z= z(i);
struct(i).name = names(i);
struct(i).year = years(i);
end
%create markersize structure based on year
uyrs = unique([struct.year]); %array of unique years
sz = linspace(10,35,length(uyrs)); %array of sizes, same length as year
for i=1:length(uyrs)
szplot(i).year = uyrs(i);
szplot(i).sz = sz(i);
end
%create color structure based on name
uname = unique({struct.name}); %array of unique names
cols = ['#8c510a';'#fc8d59';'#d8b365'];
for i=1:length(uname)
cplot(i).name = uname{i};
cplot(i).color = cols(i,:);
end
%%
n=1; %keeps track of number of years
figure; tiledlayout(1,2);
for ind=1:length(struct)
nexttile(1)
hold on;
if strcmp(struct(ind).name,'a') %conditional for x data I want to show in legend (1 per year)
cc = cplot(matches({cplot.name},struct(ind).name)).color; %finds correct color based on conditional
size = szplot(n).sz;
year = szplot(n).year;
p1(n) = scatter(struct(ind).x,struct(ind).y,size,'MarkerFaceColor',cc,'DisplayName',num2str(year)); %by giving it a handle (p1) & DisplayName, ensures desired labeled data shows up in legend
n=n+1; %keeps track of number of years
end
cc = cplot(matches({cplot.name},struct(ind).name)).color; %matches color to name
size = szplot([szplot.year]==struct(ind).year).sz; %matches size to year
scatter(struct(ind).x,struct(ind).y,size,'MarkerFaceColor',cc); %plot rest of x data
nexttile(2)
hold on;
scatter(struct(ind).z,struct(ind).y,size,'MarkerFaceColor',cc); %plot z data
drawnow;
%------> <------%
if ind==length(struct)
[lg1,obj]=legend(p1,'Orientation','Horizontal'); %creates obj to find marker size at end of plotting
end
%------> <------%
end
%------> <------%
objhl = findobj(obj, 'type', 'patch'); % finds objects in legend of type patch (e.g. marker)
for i = 1:length(objhl) %iterate through patches to set each size individually
set(objhl(i), 'Markersize', sqrt(szplot(i).sz)); % set marker size according to size structure
end
%------> <------%
lg1.Layout.Tile = 'North';
0 个评论
per isakson
2019-5-10
编辑:per isakson
2019-5-11
Short answer: The behavior described in the stackoverflow thread is based on an undocumented feature.
I've reproduce your observations with the following script, which is based on the stackoverflow thread.
%%
plot(1:10, 'o-');
hold on
plot(5:12, 'r*--'); %// example plots
[ lgd, objh ] = legend({'one plot', 'another plot'}, 'location', 'NorthWest', 'Fontsize', 14);
%% // set font size as desired
objhl = findobj( objh, 'type', 'line' ); %// objects of legend of type line
set( objhl, 'Markersize', 18 ); %// set marker size as desired
%%
savefig('matte.fig');
delete( gcf )
%%
openfig('matte.fig')
I use R2018b. The syntax used to call legend with two output arguments, [ lgd, objh ] = legend(___), is not documented. Neither is it documented in R2019a.
Furthermore, I found these two lines in legend.m
% Legend no longer supports more than one output argument
% Warn the user and ignore additional output arguments.
objh used in the stackoverflow thread is not a legend object.
>> lgd
lgd =
Legend (one plot, another plot) with properties:
String: {'one plot' 'another plot'}
Location: 'northwest'
Orientation: 'vertical'
FontSize: 14
Position: [0.1494 0.7758 0.2679 0.1250]
Units: 'normalized'
Show all properties
>> objh
objh =
6×1 graphics array:
Text (one plot)
Text (another plot)
Line (one plot)
Line (one plot)
Line (another plot)
Line (another plot)
[...] For some reason, when I save the figure as a .fig, the legend title isn’t saved.
My guess:
- savefig doesn't save the legend
- openfig creates a default legend (How does it know it should do that?)
2 个评论
per isakson
2019-5-17
编辑:per isakson
2019-5-17
"even more bizzare" By design Matlab exposes a limited number of properties to the user. In this case fontsize, but not markersize.
[...] Starting in R2014b, graphics handles are object handles of various types, depending on the class of the graphics object. Graphics objects now behave like other MATLAB® objects.
"[...] guess there is no solution so far" There are two approaches, which might be worth trying
- Modify the Save and Load Process
- A Java-solution, see Undocumented Matlab and Undocumented Secrets of Matlab-Java Programming
Mona Lacatusu
2019-9-3
编辑:per isakson
2020-2-4
For me it worked to change the marker size from a loaded image in the following way:
image1 = hgload('image_path/file_name.fig');
figure
h(1)=subplot(2,1,1);
copyobj(allchild(get(image1,'CurrentAxes')),h(1));
% Add legends
[~, objh]=legend(h(1),'Data1','Data2','Data3','Location','best')
objhl = findobj(objh, 'type', 'Line'); % objects of legend of type Line
set(objhl, 'Markersize', 40); % set marker size as desired
1 个评论
Carl Witthoft
2020-2-4
Mona, what version of MATLAB are you using to get that success? Nobody I've found yet can get this to work with any 2019 version
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Legend 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!