如何在 MATLAB 中实现已弃用的完整十字线指针功能?
How can I implement the deprecated full crosshair pointer functionality in MATLAB?
我正在尝试将图表上的指针替换为完整的十字准线(即一组 2 条垂直线,垂直和水平延伸到图表的边缘并跟随鼠标光标)。多年前,我能够用这行代码完成此操作:
set(gcf,'Pointer','fullcross')
但是,当我现在尝试 运行 这一行时,我收到以下消息:
Warning: Full crosshair pointer is no longer supported. A crosshair pointer will be used instead.
我真的很想找到一种替代方法来实现此功能,但到目前为止一直无法实现。我遇到了以下功能:MYGINPUT,但它似乎没有完成我正在寻找的功能。有人有什么建议吗?
您实际上可以通过向您的图形添加一个 'WindowButtonMotionFcn'
来做到这一点(假设没有其他任何东西正在使用它),当您的鼠标悬停在它上面时,它会在您的坐标轴上显示十字准线。这是一个为图中所有轴创建此类功能的函数:
function full_crosshair(hFigure)
% Find axes children:
hAxes = findall(hFigure, 'Type', 'axes');
% Get all axes limits:
xLimits = get(hAxes, 'XLim');
xLimits = vertcat(xLimits{:});
yLimits = get(hAxes, 'YLim');
yLimits = vertcat(yLimits{:});
% Create lines (not displayed yet due to NaNs) and listeners:
for iAxes = 1:numel(hAxes)
hHoriz(iAxes) = line(xLimits(iAxes, :), nan(1, 2), 'Parent', hAxes(iAxes));
hVert(iAxes) = line(nan(1, 2), yLimits(iAxes, :), 'Parent', hAxes(iAxes));
listenObj(iAxes) = addlistener(hAxes(iAxes), {'XLim', 'YLim'}, ...
'PostSet', @(~, ~) update_limits(iAxes));
end
% Set callback on the axes parent to the nested function below:
set(hFigure, 'WindowButtonMotionFcn', @show_lines);
function update_limits(axesIndex)
xLimits(axesIndex, :) = get(hAxes(axesIndex), 'XLim');
yLimits(axesIndex, :) = get(hAxes(axesIndex), 'YLim');
set(hHoriz(axesIndex), 'XData', xLimits(axesIndex, :));
set(hVert(axesIndex), 'YData', yLimits(axesIndex, :));
end
function show_lines(~, ~)
% Get current cursor positions in axes:
cursorPos = get(hAxes, 'CurrentPoint');
cursorPos = vertcat(cursorPos{:});
cursorPos = cursorPos(1:2:end, 1:2);
% Determine if the cursor is within an axes:
inAxes = (cursorPos(:, 1) >= xLimits(:, 1)) & ...
(cursorPos(:, 1) <= xLimits(:, 2)) & ...
(cursorPos(:, 2) >= yLimits(:, 1)) & ...
(cursorPos(:, 2) <= yLimits(:, 2));
% Update lines and cursor:
if any(inAxes) % Cursor within an axes
set(hFigure, 'Pointer', 'custom', 'PointerShapeCData', nan(16));
set(hHoriz(inAxes), {'YData'}, num2cell(cursorPos(inAxes, 2)*[1 1], 2));
set(hVert(inAxes), {'XData'}, num2cell(cursorPos(inAxes, 1)*[1 1], 2));
set(hHoriz(~inAxes), 'YData', nan(1, 2));
set(hVert(~inAxes), 'XData', nan(1, 2));
else % Cursor outside axes
set(hFigure, 'Pointer', 'arrow');
set(hHoriz, 'YData', nan(1, 2));
set(hVert, 'XData', nan(1, 2));
end
end
end
如果您执行以下操作:
full_crosshair(gcf);
然后当您将光标移到图中的每个轴上时,光标将消失,您将看到两条线出现并跟踪鼠标位置。如果任何轴限制发生变化,则上述代码中的 event listeners 将检测并解决它。如果在图中添加或删除轴,您将需要再次调用 full_crosshair
以相应地更新 'WindowButtonMotionFcn'
。
最后,您只需清除 'WindowButtonMotionFcn'
即可将其关闭:
set(gcf, 'WindowButtonMotionFcn', []);
我正在尝试将图表上的指针替换为完整的十字准线(即一组 2 条垂直线,垂直和水平延伸到图表的边缘并跟随鼠标光标)。多年前,我能够用这行代码完成此操作:
set(gcf,'Pointer','fullcross')
但是,当我现在尝试 运行 这一行时,我收到以下消息:
Warning: Full crosshair pointer is no longer supported. A crosshair pointer will be used instead.
我真的很想找到一种替代方法来实现此功能,但到目前为止一直无法实现。我遇到了以下功能:MYGINPUT,但它似乎没有完成我正在寻找的功能。有人有什么建议吗?
您实际上可以通过向您的图形添加一个 'WindowButtonMotionFcn'
来做到这一点(假设没有其他任何东西正在使用它),当您的鼠标悬停在它上面时,它会在您的坐标轴上显示十字准线。这是一个为图中所有轴创建此类功能的函数:
function full_crosshair(hFigure)
% Find axes children:
hAxes = findall(hFigure, 'Type', 'axes');
% Get all axes limits:
xLimits = get(hAxes, 'XLim');
xLimits = vertcat(xLimits{:});
yLimits = get(hAxes, 'YLim');
yLimits = vertcat(yLimits{:});
% Create lines (not displayed yet due to NaNs) and listeners:
for iAxes = 1:numel(hAxes)
hHoriz(iAxes) = line(xLimits(iAxes, :), nan(1, 2), 'Parent', hAxes(iAxes));
hVert(iAxes) = line(nan(1, 2), yLimits(iAxes, :), 'Parent', hAxes(iAxes));
listenObj(iAxes) = addlistener(hAxes(iAxes), {'XLim', 'YLim'}, ...
'PostSet', @(~, ~) update_limits(iAxes));
end
% Set callback on the axes parent to the nested function below:
set(hFigure, 'WindowButtonMotionFcn', @show_lines);
function update_limits(axesIndex)
xLimits(axesIndex, :) = get(hAxes(axesIndex), 'XLim');
yLimits(axesIndex, :) = get(hAxes(axesIndex), 'YLim');
set(hHoriz(axesIndex), 'XData', xLimits(axesIndex, :));
set(hVert(axesIndex), 'YData', yLimits(axesIndex, :));
end
function show_lines(~, ~)
% Get current cursor positions in axes:
cursorPos = get(hAxes, 'CurrentPoint');
cursorPos = vertcat(cursorPos{:});
cursorPos = cursorPos(1:2:end, 1:2);
% Determine if the cursor is within an axes:
inAxes = (cursorPos(:, 1) >= xLimits(:, 1)) & ...
(cursorPos(:, 1) <= xLimits(:, 2)) & ...
(cursorPos(:, 2) >= yLimits(:, 1)) & ...
(cursorPos(:, 2) <= yLimits(:, 2));
% Update lines and cursor:
if any(inAxes) % Cursor within an axes
set(hFigure, 'Pointer', 'custom', 'PointerShapeCData', nan(16));
set(hHoriz(inAxes), {'YData'}, num2cell(cursorPos(inAxes, 2)*[1 1], 2));
set(hVert(inAxes), {'XData'}, num2cell(cursorPos(inAxes, 1)*[1 1], 2));
set(hHoriz(~inAxes), 'YData', nan(1, 2));
set(hVert(~inAxes), 'XData', nan(1, 2));
else % Cursor outside axes
set(hFigure, 'Pointer', 'arrow');
set(hHoriz, 'YData', nan(1, 2));
set(hVert, 'XData', nan(1, 2));
end
end
end
如果您执行以下操作:
full_crosshair(gcf);
然后当您将光标移到图中的每个轴上时,光标将消失,您将看到两条线出现并跟踪鼠标位置。如果任何轴限制发生变化,则上述代码中的 event listeners 将检测并解决它。如果在图中添加或删除轴,您将需要再次调用 full_crosshair
以相应地更新 'WindowButtonMotionFcn'
。
最后,您只需清除 'WindowButtonMotionFcn'
即可将其关闭:
set(gcf, 'WindowButtonMotionFcn', []);