2013-12-06 3 views
4

Я установил WindowButtonMotionFcn на мой обратный вызов, который отображает три графика, с данными в зависимости от положения мыши. Однако для MATLAB это слишком сложно, потому что после перемещения мыши немного, графический интерфейс перестает отвечать на запросы.Matlab gui WindowButtonMotionFcn сбой при вызове слишком часто?

Я использую этот код (скопированные части от кого-то):

set(handles.figure1, 'windowbuttonmotionfcn', @hover_Callback); 

function hover_Callback(hObject, handles, eventdata) 
inside = false; 

pos = get(handles.axes1, 'currentpoint'); 
xlim = get(handles.axes1, 'XLim'); 
ylim = get(handles.axes1, 'YLim'); 

if (pos(1,1) > max(xlim(1), 1) && ... 
     pos(1,1) < xlim(2) && ... 
     pos(1,2) > ylim(1) && ... 
     pos(1,2) < ylim(2)) 
    inside = true; 
end 
if ~inside 
    return 
end 
ix = round(pos(1,1)); 
iy = round(pos(2,2)); 
axes(handles.axes2); cla; plot(squeeze(t2(ix,iy,:)), squeeze(d2(ix,iy,:))); 
axes(handles.axes3); cla; plot(squeeze(t3(ix,iy,:)), squeeze(d3(ix,iy,:))); 
axes(handles.axes4); cla; plot(squeeze(t4(ix,iy,:)), squeeze(d4(ix,iy,:))); 

Это вызывает мой графический интерфейс перестает отвечать на запросы, без кодов ошибок. Если я уйду из него и начну его снова, все MATLAB перестанут отвечать. Кто-нибудь знает, что может произойти, и как я могу это исправить? Может быть, я как-то забиваю себе память?

ответ

2

Когда обратный вызов вызывается с высокой частотой, существует опасность того, что он будет вызван снова до завершения другого вызова (то есть re-entrancy). С WindowButtonMotionFcn, есть неплохой шанс, что это произойдет.

Вы можете предотвратить повторное включение обратного вызова, проверив стек вызовов функций (вывод dbstack) для нескольких вызовов ответственного обратного вызова. Очень простая, но умная реализация такой проверки под названием isMultipleCall представлена ​​in a post on undocumentedmatlab.com. Идея состоит в том, чтобы подсчитать количество раз, когда имя функции обратного вызова отображается в стеке. Возьмите действительную функцию непосредственно из undocumentedmatlab.com, но перегоняется к следующему:

function flag=isMultipleCall() 
s = dbstack(); 
% s(1) corresponds to isMultipleCall 
if numel(s)<=2, flag=false; return; end 
% compare all functions on stack to name of caller 
count = sum(strcmp(s(2).name,{s(:).name})); 
% is caller re-entrant? 
if count>1, flag=true; else flag=false; end 

Использование isMultipleCall очень просто. Помещенный запустить его в верхней части обратного вызова (в данном случае, hover_Callback), и под залог, если это указывает на то, что несколько вызовов в процессе:

function hover_Callback(hObject, eventdata, handles) 

if isMultipleCall(); return; end 

... 

end 

Это предотвращает обратный вызов от выполнения полностью, пока предыдущие вызовы не прекращаются , Только чек будет работать, пропуская интенсивные операции графического объекта (т.е. axes, plot и т.д.)


alternative approach является использование listener для WindowButtonMotionEvent:

handles.motion = handle.listener(gcf,'WindowButtonMotionEvent',@hover_callback2); 

Тогда в обратном вызове проверьте свойство eventdata.CurrentPoint вместо currentpoint. Проверьте повторное включение, как указано выше.

Если вы не используете GUIDE и не имеют handles структура управляется guidata, а затем вызвать слушателю что-то вроде motionListener и использовать setappdata для хранения слушателя. Например,

setappdata(hFigure,'mouseMotion',motionListener); 

Просто использовать известную ручку любого объекта в графическом интерфейсе so the listener persists. Вы также можете использовать UserData вместо setappdata, или any other way of managing GUI data.


Как и в сторону, обратите внимание, что команда axes довольно медленно, и можно избежать путем пропускания оси рукоятку plot непосредственно:

plot(handles.axes2, squeeze(t2(ix,iy,:)), squeeze(d2(ix,iy,:))); 
+0

Очень хорошо объяснено, еще раз спасибо за вашу помощь. – Leo

+0

@Leo Ваш прием. Я рад, что это сработало - я не был уверен, что это будет сделано. – chappjc

+0

Это был мгновенный рельеф! – Leo

Смежные вопросы