KiW*_*KiW 1 matlab plot legend word-wrap matlab-figure
我有一个多线的情节,我想在框下面显示图例(southoutside).问题是目前我的传奇太长了,无法放在一条线上.因此问题是我如何在传奇中获得换行符?
目前我生成的图例如下:
hLegend = legend([l1,l2,l3,l4], 'This is a very, very long legend text', 'Test2', ...
'A bit longer', 'This is quite long');
set(hLegend,'Fontsize',8,'Location', 'southoutside', 'Orientation','horizontal');
Run Code Online (Sandbox Code Playgroud)
那么这会发生:
如你所见,我有四行(可能会有更多),第一行有一个很长的名字.
我希望以这种方式保持方向以减少所需的图形空间,并且如果图例超出图片宽度(即之前l3或l4此处用黄色或紫色线表示),我想要设置自动换行符.
有什么想法吗?我使用的宽度为15.75厘米.
编辑
非常感谢到目前为止的答案.虽然这两个答案都提供了将图例分成两行的机会,但我的主要问题仍然存在.如果假设现在,该地块有更多然后四行,可以说20,我想有传说南边,它使用最小的空间的方式水平,是有办法不拆的传说中的一个图例文本,但后一个条目.我生成了一个新的数字,通常描绘了我正在寻找的东西(它在Paint中制作,因此它只是显示了一般的想法).
编辑2
columnlegend遗憾的是,Matlab文件交换中可用的包不支持图中的图例(至少说明中没有指定选项,它只列出以下可能的位置:'NorthWest','NorthEast','SouthEast','SouthWest "
感谢帮助.
这是传说文本包装的概念验证,使用了一些未记录的输出legend和MATLAB -> python界面.我将首先展示代码,然后简要解释它为何/如何工作.
这是在MATLAB 2016a中完成的.
function q39456339
%% Definitions:
MAX_LENGTH_IN_CHARS = 20;
OPTION = 2;
%% Plot something:
x = 1:10;
figure('Position',[450 400 800 270]);
plot(x,x,x,2*x,x,10-x,x,20-2*x);
%% Using python's TextWrapper to wrap entries:
% web(fullfile(docroot, 'matlab/matlab_external/call-python-from-matlab.html'))
switch OPTION
case 1
[~,hT] = legend({'This is a very, very long legend text', 'Test2', 'A bit longer', ...
'This is quite long'},'Location', 'SouthOutside', 'Orientation','Horizontal',...
'Fontsize',8,'Box','Off');
texts = hT(arrayfun(@(x)isa(x,'matlab.graphics.primitive.Text'),hT));
wrapLegendTexts(texts,MAX_LENGTH_IN_CHARS);
case 2
hL = legend({'This is a very, very long legend text', 'Test2', 'A bit longer', ...
'This is quite long'},'Location', 'SouthOutside', 'Orientation','Horizontal',...
'Fontsize',8,'Interpreter','tex');
TEX_NEWLINE = '\newline';
addNewlinesThroughPython(hL, MAX_LENGTH_IN_CHARS, TEX_NEWLINE);
end
end
%% Helper functions:
function wrapLegendTexts(textObjs,maxlen)
tw = py.textwrap.TextWrapper(pyargs('width', int32(maxlen)));
for ind1 = 1:numel(textObjs)
wrapped = cellfun(@char,cell(wrap(tw,textObjs(ind1).String)), 'UniformOutput', false);
textObjs(ind1).Text.String = reshape(wrapped,[],1);
end
end
function addNewlinesThroughPython(hLeg, maxlen, newlineStr)
tw = py.textwrap.TextWrapper(pyargs('width', int32(maxlen)));
for ind1 = 1:numel(hLeg.PlotChildren)
hLeg.PlotChildren(ind1).DisplayName = char(...
py.str(newlineStr).join(wrap(tw,hLeg.PlotChildren(ind1).DisplayName)));
end
end
Run Code Online (Sandbox Code Playgroud)
首先,让我们来看看签名legend:
>> dbtype legend 1
1 function [leg,labelhandles,outH,outM] = legend(varargin)
Run Code Online (Sandbox Code Playgroud)
我们可以看到第二个输出返回某种句柄.当我们进一步调查时:
arrayfun(@class, hT, 'UniformOutput', false)
ans =
'matlab.graphics.primitive.Text'
'matlab.graphics.primitive.Text'
'matlab.graphics.primitive.Text'
'matlab.graphics.primitive.Text'
'matlab.graphics.primitive.Line'
'matlab.graphics.primitive.Line'
'matlab.graphics.primitive.Line'
'matlab.graphics.primitive.Line'
'matlab.graphics.primitive.Line'
'matlab.graphics.primitive.Line'
'matlab.graphics.primitive.Line'
'matlab.graphics.primitive.Line'
Run Code Online (Sandbox Code Playgroud)
和:
hT(1)
ans =
Text (This is a very, very long legend text) with properties:
String: 'This is a very, very long legend text'
FontSize: 9
FontWeight: 'normal'
FontName: 'Helvetica'
Color: [0 0 0]
HorizontalAlignment: 'left'
Position: [0.0761 0.5128 0]
Units: 'data'
Show all properties
Run Code Online (Sandbox Code Playgroud)
啊哈!这是第一个图例文本条目.我们在上面的列表中看到了几个有趣的属性(这里有更多),但我们关心的是String.
那么这是一个如何包装所述字符串的问题.幸运的是,这正是MATLAB文档中提供的使用python 接口的示例,因此我不会详细介绍它.这是python文档的textwrap链接.页面的正确版本(可通过左上角的下拉列表选择)应与您的本地python版本相对应(请参阅输出pyversion).
我的其余代码只是python接口的包装器,用于处理所有图例条目.
这里我们不使用任何额外的输出legend,而是修改hLeg.PlotChildren.DisplayName.此属性不接受字符串的单元格数组(多行字符串的方式通常在MATLAB中定义),因此我们需要根据解释器识别的语法插入换行符"标记"(..或字符10 - ASCII值一个"换行符",如excaza的回答所示).找到换行符的正确位置仍然是使用python完成的,但这次是join编辑字符串(中间有换行符标记)而不是转换为cell列.
Texts' Position参数来使图例看起来更好一些legend会略微改变它的行为(您可以从上图中的重叠图例条目中看到它).| 归档时间: |
|
| 查看次数: |
3526 次 |
| 最近记录: |