如何在 Matlab 图形中添加工具提示或叠加文本
How to add tooltips or overlay text in a Matlab figure
我有一个包含两条或更多条线的图形。这些线有额外的、与之相关的重要信息,比如平均有多少数据点来创建线等。我想在我的图中访问这些信息。
我认为一个很好的解决方案是,如果您可以将鼠标悬停在一行上并获取扩展信息。
然而搜索 tooltips/overlays/hover-over 数字似乎没有结果。
示例:
figure; hold on;
plot(1:10,rand(10,1))
plot(1:10,rand(10,1))
% additional info
plot_1_info.name = 'Alice';
plot_2_info.name = 'Bob';
plot_1_info.age = 24;
plot_2_info.age = 12;
对此有什么好的解决方案或更好的方法吗?
您可以更改数据游标行为,此选项具有良好的向后兼容性(我在 R2017b 中测试了以下内容,之前在 15b 中使用类似)。
详情见我的评论:
% Create some data
x = (1:2:20).';
y = rand(10,1);
name = { 'Alice'; 'Alice'; 'Alice'; 'Alice'; 'Bob'; 'Bob'; 'Bob'; 'Chris'; 'Chris'; 'Chris' };
age = [ 24; 24; 24; 24; 12; 12; 12; 17; 17; 17 ];
% Put it in a table, so we have it all together for indexing as plot data
tbl = table( x, y, name, age );
% Create the plot, assign the UserData property to the plot object
f = figure;
plt = plot( x, y );
plt.UserData = tbl;
% Hijack the Data Cursor update callback so we can inject our own info
dcm = datacursormode( f );
set( dcm, 'UpdateFcn', @onDataCursor );
% Function which returns the text to be displayed on the data cursor
function txt = onDataCursor( ~, evt )
% Get containing figure
f = ancestor( evt.Target, 'figure' );
% Get the index within the original data
idx = getfield( getCursorInfo( datacursormode( f ) ), 'DataIndex' );
% The original data is stored in the UserData property
data = evt.Target.UserData;
% Each element of the cell array is a new line on the cursor
txt = { sprintf( 'X: %g', data.x(idx) ), ...
sprintf( 'Y: %g', data.y(idx) ), ...
sprintf( 'Name: %s', data.name{idx} ), ...
sprintf( 'Age: %g', data.age(idx) ) };
end
输出:
注意:我没有处理过不止一个数据游标提示的情况。您可以轻松地在回调中实现 idx
循环来处理这个问题,我把它留作练习。
这种方法非常灵活。例如,如果我们有 3 行(每个 'person' 一行),那么它们可以各自拥有自己的 UserData
结构,并且我们不需要重复 table 行中的所有信息。
A = struct( 'X', 1:4, 'Y', rand(1,4), 'Name', 'Alice', 'Age', 24 );
B = struct( 'X', 1:3, 'Y', rand(1,3), 'Name', 'Bob', 'Age', 12 );
C = struct( 'X', 1:3, 'Y', rand(1,3), 'Name', 'Chris', 'Age', 17 );
f = figure; hold on;
plt = plot( A.X, A.Y ); plt.UserData = A;
plt = plot( B.X, B.Y ); plt.UserData = B;
plt = plot( C.X, C.Y ); plt.UserData = C;
% ... Now the struct fields can be accessed from the callback
使用new data tip customization system introduced in R2019a,我们可以做以下事情:
figure(); hP = plot(1:10,rand(10,1),1:10,rand(10,1));
nPts = cellfun(@numel, {hP.XData});
hP(1).DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('Name', repmat("Alice",nPts(1),1) );
hP(1).DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('Age', repmat(12, nPts(1),1) );
hP(2).DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('Name', repmat("Bob", nPts(2),1) );
hP(2).DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('Age', repmat(24, nPts(2),1) );
% (Of course the above can be organized in a nicer way using a function)
产生:
请注意 "hover datatip" 有黑色文本,而 "click datatip" 有蓝色文本 - 这是默认行为。
我有一个包含两条或更多条线的图形。这些线有额外的、与之相关的重要信息,比如平均有多少数据点来创建线等。我想在我的图中访问这些信息。
我认为一个很好的解决方案是,如果您可以将鼠标悬停在一行上并获取扩展信息。
然而搜索 tooltips/overlays/hover-over 数字似乎没有结果。
示例:
figure; hold on;
plot(1:10,rand(10,1))
plot(1:10,rand(10,1))
% additional info
plot_1_info.name = 'Alice';
plot_2_info.name = 'Bob';
plot_1_info.age = 24;
plot_2_info.age = 12;
对此有什么好的解决方案或更好的方法吗?
您可以更改数据游标行为,此选项具有良好的向后兼容性(我在 R2017b 中测试了以下内容,之前在 15b 中使用类似)。
详情见我的评论:
% Create some data
x = (1:2:20).';
y = rand(10,1);
name = { 'Alice'; 'Alice'; 'Alice'; 'Alice'; 'Bob'; 'Bob'; 'Bob'; 'Chris'; 'Chris'; 'Chris' };
age = [ 24; 24; 24; 24; 12; 12; 12; 17; 17; 17 ];
% Put it in a table, so we have it all together for indexing as plot data
tbl = table( x, y, name, age );
% Create the plot, assign the UserData property to the plot object
f = figure;
plt = plot( x, y );
plt.UserData = tbl;
% Hijack the Data Cursor update callback so we can inject our own info
dcm = datacursormode( f );
set( dcm, 'UpdateFcn', @onDataCursor );
% Function which returns the text to be displayed on the data cursor
function txt = onDataCursor( ~, evt )
% Get containing figure
f = ancestor( evt.Target, 'figure' );
% Get the index within the original data
idx = getfield( getCursorInfo( datacursormode( f ) ), 'DataIndex' );
% The original data is stored in the UserData property
data = evt.Target.UserData;
% Each element of the cell array is a new line on the cursor
txt = { sprintf( 'X: %g', data.x(idx) ), ...
sprintf( 'Y: %g', data.y(idx) ), ...
sprintf( 'Name: %s', data.name{idx} ), ...
sprintf( 'Age: %g', data.age(idx) ) };
end
输出:
注意:我没有处理过不止一个数据游标提示的情况。您可以轻松地在回调中实现 idx
循环来处理这个问题,我把它留作练习。
这种方法非常灵活。例如,如果我们有 3 行(每个 'person' 一行),那么它们可以各自拥有自己的 UserData
结构,并且我们不需要重复 table 行中的所有信息。
A = struct( 'X', 1:4, 'Y', rand(1,4), 'Name', 'Alice', 'Age', 24 );
B = struct( 'X', 1:3, 'Y', rand(1,3), 'Name', 'Bob', 'Age', 12 );
C = struct( 'X', 1:3, 'Y', rand(1,3), 'Name', 'Chris', 'Age', 17 );
f = figure; hold on;
plt = plot( A.X, A.Y ); plt.UserData = A;
plt = plot( B.X, B.Y ); plt.UserData = B;
plt = plot( C.X, C.Y ); plt.UserData = C;
% ... Now the struct fields can be accessed from the callback
使用new data tip customization system introduced in R2019a,我们可以做以下事情:
figure(); hP = plot(1:10,rand(10,1),1:10,rand(10,1));
nPts = cellfun(@numel, {hP.XData});
hP(1).DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('Name', repmat("Alice",nPts(1),1) );
hP(1).DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('Age', repmat(12, nPts(1),1) );
hP(2).DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('Name', repmat("Bob", nPts(2),1) );
hP(2).DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('Age', repmat(24, nPts(2),1) );
% (Of course the above can be organized in a nicer way using a function)
产生:
请注意 "hover datatip" 有黑色文本,而 "click datatip" 有蓝色文本 - 这是默认行为。