Как я могу реализовать устаревшую функциональность указателя полного перекрестия в MATLAB?


Я пытаюсь заменить указатель на графике полным перекрестием (то есть набором из 2 перпендикулярных линий, которые тянутся к краям графика вертикально и горизонтально и следуют за курсором мыши). Много лет назад я смог сделать это с помощью следующей строки кода:

set(gcf,'Pointer','fullcross')

Однако, когда я пытаюсь запустить эту строку сейчас, я получаю следующее сообщение:

Warning: Full crosshair pointer is no longer supported. A crosshair pointer will be used instead.

Я бы очень хотел найти альтернативный способ реализации этой функциональности, но не смог этого сделать. далеко. Я столкнулся со следующей функцией: MYGINPUT , но она, похоже, не выполняет то, что я ищу. У кого-нибудь есть предложения?

1 4

1 ответ:

Вы действительно можете сделать это, добавив '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);

Затем, когда вы наведете курсор на каждую ось на вашем рисунке, курсор исчезнет, и вы увидите, как появляются две линии и отслеживают положение мыши. Если любая из осей ограничивает изменение, то слушатели событий в приведенном выше коде обнаружат и учтут его. Если оси добавлены или удалены из рисунка, вам нужно будет снова вызвать full_crosshair, чтобы обновить 'WindowButtonMotionFcn' соответственно.

Наконец, вы можете отключить его, просто очистив 'WindowButtonMotionFcn':

set(gcf, 'WindowButtonMotionFcn', []);