Почему обратный вызов 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