Cursor line

76 次查看(过去 30 天)
Mtlb Usr
Mtlb Usr 2011-2-14
Hi,
I've got a figure with several subplots. These subplots are located one under the other one. Then, that I want to do is create a vertical cursor to across all subplots and when I'm going to move this appear the current values of all subplots.
How can I develop this?
thanks
regards

采纳的回答

Matt Fig
Matt Fig 2011-2-14
This can be done with a little handle graphics. I don't have time right now to make this code perfect (error checking, special cases handling, commenting(!), etc.), but it should give you something of an idea. Run this function then hit the left and right arrow to see what happens.
function [] = data_subplots()
% Link data cursors so that they track accross subplots.
% Create the subplots.
% Alternatively, use GET to create s and L from existing plots.
x = 1:.1:10;
for ii = 1:3
s(ii) = subplot(3,1,ii);
L(ii) = plot(x,sin(x/ii)*ii);
end
% Now start the work.
for ii = 1:length(s)
S.D{ii} = get(L(ii),{'xdata','ydata'});
S.L(ii) = length(S.D{ii}{1});
S.M(ii) = floor(S.L(ii)/2);
S.DF = diff(S.D{ii}{1}(S.M(ii):S.M(ii)+1)); % uniform assum
S.I(ii) = S.M(ii);
S.T(ii) = text(S.D{ii}{1}(S.M(ii)+2),S.D{ii}{2}(S.M(ii)+2),'here');
set(S.T(ii),'string',{['X: ',sprintf('%3.3g',S.D{ii}{1}(S.M(ii)))];...
['Y: ',sprintf('%3.3g',S.D{ii}{2}(S.M(ii)))]},...
'parent',s(ii),'backgroundco',[.8 .8 0]);
set(s(ii),'nextplot','add')
S.F(ii) = plot(s(ii),S.D{ii}{1}(S.M(ii)),S.D{ii}{2}(S.M(ii)),'sk');
set(S.F(ii),'markerfacec','b')
end
set(gcf,'keypressfcn',{@fh_kpfcn,S})
function [] = fh_kpfcn(varargin)
D = varargin{2}.Key;
S = varargin{3};
if strcmp(D,'leftarrow')
for ii = 1:length(S.T)
if S.I(ii)~=1
S.I(ii) = S.I(ii)-1;
set(S.F(ii),'xdata',S.D{ii}{1}(S.I(ii)),...
'ydata',S.D{ii}{2}(S.I(ii)))
set(S.T(ii),'position',...
[S.D{ii}{1}(S.I(ii))+S.DF*2,S.D{ii}{2}(S.I(ii))],...
'string',{['X: ',sprintf('%3.3g',S.D{ii}{1}(S.I(ii)))];...
['Y: ',sprintf('%3.3g',S.D{ii}{2}(S.I(ii)))]})
end
end
elseif strcmp(D,'rightarrow')
for ii = 1:length(S.T)
if S.I(ii)~=S.L(ii)
S.I(ii) = S.I(ii)+1;
set(S.F(ii),'xdata',S.D{ii}{1}(S.I(ii)),...
'ydata',S.D{ii}{2}(S.I(ii)))
set(S.T(ii),'position',...
[S.D{ii}{1}(S.I(ii))+S.DF*2,S.D{ii}{2}(S.I(ii))],...
'string',{['X: ',sprintf('%3.3g',S.D{ii}{1}(S.I(ii)))];...
['Y: ',sprintf('%3.3g',S.D{ii}{2}(S.I(ii)))]})
end
end
end
set(gcf,'keypressfcn',{@fh_kpfcn,S}) % Update the structure.
  3 个评论
Mtlb Usr
Mtlb Usr 2011-2-15
Hi,
I hadn't realized!!! I can move the datatips with by arrow's key of pc.
I think that with this solution I will resolve my question.
Thank you so much
regards
Matthias Luh
Matthias Luh 2022-3-19
This is awesome, thank you! I extended the function a bit and tried to make it more readable for me (see below).
For others looking for help: Also have a look the solution jiro posted here: http://www.mathworks.com/matlabcentral/answers/1758-crosshairs-or-just-vertical-line-across-linked-axis-plots
It might be more intuitive because it allows clicking instead of using the arrow keys.
Dear MATLAB team, if you read this: please add a simple and intuitive crosshair function that can be easily used and activated, e.g. also in the GUI. Something like used in Grafana: https://play.grafana.org/
Extension of Matt Fig's code:
  • compatibility with datetime x-axis
  • use "shift" + left/right to move around faster
  • variable to adjust offset of the textbox relative to data point (textbox_dx_offset, 2x)
  • created an own function to generates the text so you only need to adjust it once
function [] = data_subplots_2()
% Link data cursors so that they track accross subplots.
% Create the subplots.
% Alternatively, use GET to create s and L from existing plots.
x = 1:.1:10;
for ii = 1:3
subpl(ii) = subplot(3,1,ii);
pl(ii) = plot(x,sin(x/ii)*ii);
end
% Data tool tip
% https://de.mathworks.com/matlabcentral/answers/1308-cursor-line
textbox_dx_offset = 3;
for ii = 1:length(subpl) % for each subplot
S.data_x{ii} = get(pl(ii), 'xdata');
S.data_y{ii} = get(pl(ii), 'ydata');
S.datalength(ii) = length(S.data_x{ii});
S.startindex(ii) = floor(S.datalength(ii) / 2);
S.delta_x = diff(S.data_x{ii}(S.startindex(ii):(S.startindex(ii) + 1))); % assume uniform x-axis data difference
S.index(ii) = S.startindex(ii);
S.text(ii) = text(S.data_x{ii}(S.startindex(ii) + textbox_dx_offset), S.data_y{ii}(S.startindex(ii) + textbox_dx_offset),'here');
set(S.text(ii), 'string', get_tooltip_text(S, ii), 'parent', subpl(ii), 'BackgroundColor', [1 1 1], 'EdgeColor', [0 0 0]);
set(subpl(ii), 'nextplot', 'add')
S.tooltip_point(ii) = plot(subpl(ii), S.data_x{ii}(S.startindex(ii)), S.data_y{ii}(S.startindex(ii)), 'sk');
set(S.tooltip_point(ii), 'markerfacec', 'b')
end
set(gcf, 'keypressfcn', {@key_press_function, S})
% "on key press" function:
function [] = key_press_function(varargin)
key_id = varargin{2}.Key;
S = varargin{3};
if (size(varargin{2}.Modifier, 2) > 0) && (strcmp(varargin{2}.Modifier{1}, 'shift') == 1)
dx_fac = 12;
else
dx_fac = 1;
end
textbox_dx_offset = 3;
if strcmp(key_id, 'leftarrow')
for ii = 1:length(S.text)
if S.index(ii) ~= 1
S.index(ii) = S.index(ii) - dx_fac;
set(S.tooltip_point(ii), 'xdata', S.data_x{ii}(S.index(ii)),...
'ydata', S.data_y{ii}(S.index(ii)))
set(S.text(ii), 'position',...
[get_text_xpos(S.data_x{ii}(S.index(ii)) + S.delta_x * textbox_dx_offset), S.data_y{ii}(S.index(ii))],...
'string', get_tooltip_text(S, ii))
end
end
elseif strcmp(key_id, 'rightarrow')
for ii = 1:length(S.text)
if S.index(ii) ~= S.datalength(ii)
S.index(ii) = S.index(ii) + dx_fac;
set(S.tooltip_point(ii),'xdata',S.data_x{ii}(S.index(ii)),...
'ydata',S.data_y{ii}(S.index(ii)))
set(S.text(ii),'position',...
[get_text_xpos(S.data_x{ii}(S.index(ii)) + S.delta_x * textbox_dx_offset), S.data_y{ii}(S.index(ii))],...
'string', get_tooltip_text(S, ii))
end
end
end
set(gcf,'keypressfcn',{@key_press_function,S}) % Update the structure.
% end of "on key press" function
% "get tooltip text" function:
function text = get_tooltip_text(S, ii)
if isa(S.data_x{ii}(S.index(ii)), 'datetime') == 1
text = {...
['X: ',sprintf('%s', datestr(S.data_x{ii}(S.index(ii))))];...
['Y: ',sprintf('%3.3g', S.data_y{ii}(S.index(ii)))]...
};
else
text = {...
['X: ',sprintf('%3.3g', S.data_x{ii}(S.index(ii)))];...
['Y: ',sprintf('%3.3g', S.data_y{ii}(S.index(ii)))]...
};
end
% end of "get tooltip text" function
% "get x-position" function:
function xpos = get_text_xpos(x_value)
if isa(x_value, 'datetime') == 1
ax1 = gca;
% dx_days = diff(ax1.XLim)/24;
x_min = ax1.XLim(1);
xpos = datenum(x_value - x_min);
else
xpos = x_value;
end
% end of "get tooltip text" function

请先登录,再进行评论。

更多回答(3 个)

Brett Shoelson
Brett Shoelson 2011-2-14
I would create a line object for each axes, and use LINKPROP to move them all (i.e., set their x positions) simultaneously. You might also take a look at Brandon Kuczenski's vline on the File Exchange.
Cheers,
Brett

Jiro Doke
Jiro Doke 2011-2-22
I posted a similar solution here.

Paulo Silva
Paulo Silva 2011-2-14
You might find useful tips inside the ginput function
edit ginput
%this function can be found inside ginput
set(fig,'pointer','fullcrosshair'); %horizontal and vertical cursor lines
  9 个评论
Paulo Silva
Paulo Silva 2011-2-14
I'm finally understanding but what you want isn't easy, at least for me and my basic matlab skills, maybe someone with more experience might help you.
Here's some websites with info, maybe you can find something useful in them
http://matlab.wikia.com/wiki/MATLAB_Wiki
http://undocumentedmatlab.com
Mtlb Usr
Mtlb Usr 2011-2-15
Hi,
OK, I'm going to visit these web pages.
Thank you
regards

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Specifying Target for Graphics Output 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by