Почему обратный вызов ButtonDownFcn моего объекта axes перестает работать после построения чего-либо?

Я создаю набор осей на фигуре и назначаю обратный вызов для его 'ButtonDownFcn' свойство вроде так:

HRaxes = axes('Parent', Figure, 'Position', [.05 .60 .9 .35],...
              'XLimMode', 'manual', 'ButtonDownFcn', @HR_ButtonDown);

Где функция обратного вызова определяется так:

function HR_ButtonDown(hObject, eventData)
  %# Do some stuff here when the axes is clicked on...
end

Обратный вызов работает нормально, пока я не нарисую что-то на осях так:

plot(HRaxes, data.HR_X, data.HR_Y, 'b');

После чего обратный вызов больше не срабатывает, когда я нажимаю на оси. Что не так и как я могу это исправить?

2 ответа

Решение

Основная проблема здесь заключается в том, что функция PLOT представляет собой высокоуровневую функцию построения графика, то есть она добавляет объекты на график и изменяет существующие настройки графика. Если вы посмотрите на 'NextPlot' Свойство для объектов осей, вы увидите, что у него есть три параметра, которые определяют, как высокоуровневые функции построения графиков могут влиять на объект осей:

  • add - Используйте существующие оси для рисования графических объектов.

  • replace - Сбросить все свойства осей, кроме Position по умолчанию и удалите все дочерние оси перед отображением графики (эквивалентно cla reset).

  • replacechildren - Удалить все дочерние объекты, но не сбрасывать свойства осей (эквивалентно cla).

поскольку 'replace' является настройкой по умолчанию, ручка, которую вы установили для 'ButtonDownFcn' обратный вызов сбрасывается в ничто при вызове PLOT, таким образом отключая поведение при нажатии кнопки. Есть два способа избежать этого:

  • Настройка 'NextPlot' свойство осей либо 'add' (добавить к существующим объектам сюжета) или 'replacechildren' (чтобы заменить существующие объекты графика, но сохранить текущие настройки свойств осей) перед вызовом PLOT.

    HRaxes = axes('Parent', Figure, 'Position', [.05 .60 .9 .35],...
                  'XLimMode', 'manual', 'ButtonDownFcn', @HR_ButtonDown,...
                  'NextPlot', 'add');
    plot(HRaxes, data.HR_X, data.HR_Y, 'b');
    
  • Используя низкоуровневую процедуру построения графиков (например, LINE), которая не изменяет существующие свойства графиков:

    HRaxes = axes('Parent', Figure, 'Position', [.05 .60 .9 .35],...
                  'XLimMode', 'manual', 'ButtonDownFcn', @HR_ButtonDown);
    line(data.HR_X, data.HR_Y, 'Parent', HRaxes, 'Color', 'b');
    

@ Дэвид Снайдер, заметьте, что image объект может иметь ButtonDownFcn свойство обратного вызова также. Тогда в вашем обратном вызове вы можете получить доступ к соответствующему axes собственность через Parent собственность или ancestor функция. Например, скажем, вы хотите использовать в обратном вызове ButtonDownFcn положение пикселя и кнопку, по которой вы щелкнули. Когда вы строите изображение, используйте

imh = image(some_image);
set(imh,'ButtonDownFcn',@position_and_button);

где вы определили свой обратный вызов где-то еще

function position_and_button(hObject,eventdata)
   Position = get( ancestor(hObject,'axes'), 'CurrentPoint' );
   Button = get( ancestor(hObject,'figure'), 'SelectionType' );
   %# do stuff with Position and Button
Другие вопросы по тегам