xlim listener for zoom reset and linkaxes strange behavior

조회 수: 20 (최근 30일)
Jim Hokanson
Jim Hokanson 2017년 11월 26일
댓글: Jim Hokanson 2021년 4월 15일
I've attached a 'XLim' listener to an axes object.
I had been previously using a timer due to issues with catching the events appropriately (for reasons I can't exactly remember). Now they're starting to come back to me ...
Here's some basic test code (from 2017b):
ax = gca;
plot(1:100)
L1 = addlistener(ax, 'XLim', 'PostSet', @(x,y)disp(y.AffectedObject.XLim));
When I zoom in my listener fires properly. However, when I double-click to reset the zoom (or right click and reset) no listener is fired! The 'XLim' property clearly changed but Matlab doesn't seem to care to inform me of this fact.
This seems like a bug to me. Looking at SO there is a suggestion that I listen to the zoom callback, but I'd rather not touch any callbacks since I might need 2 or more callbacks for a single axes.
Even more surprising is that by linking the axes an event is now fired on resetting the zoom. This seems to persist even if I turn the linking off.
clf
ax = gca;
plot(1:100)
L1 = addlistener(ax, 'XLim', 'PostSet', @(x,y)disp(y.AffectedObject.XLim));
linkaxes(ax,'x') %reset works as desired
linkaxes(ax,'x','off') %reset still works as desired
Questions are:
  1. How can I get a listener event for zoom reset (and pan reset) that is resistant to accidental overwriting (i.e. most likely by avoiding a single callback property)
  2. If the behavior is not a bug, why? See remark below on blog post.
  3. Why does running linkaxes fix this problem?
  4. Is there a way of accomplishing whatever the linkaxes function is doing without actually needing to modify the linkaxes behavior of the axes?
The following blog post comes to mind but it seems like a reset-zoom should trigger an event. In the linked example plotting new data that expands the x-limits doesn't throw an event. https://blogs.mathworks.com/loren/2015/12/14/axes-limits-scream-louder-i-cant-hear-you/
Update:
If you plot again the event stops getting thrown in response to resetting the zoom. ¯\_(ツ)_/¯
clf
ax = gca;
plot(1:100)
L1 = addlistener(ax, 'XLim', 'PostSet', @(x,y)disp(y.AffectedObject.XLim));
linkaxes(ax,'x')
linkaxes(ax,'x','off')
plot(1:100) %reset not working as desired

채택된 답변

Jim Hokanson
Jim Hokanson 2017년 11월 27일
편집: Jim Hokanson 2017년 11월 27일
It turns out that there is a lot of publicly readable code behind linkaxes, or really, linkprop. After some debugging I discovered the MarkedClean event. More info on this interesting event can be found at: https://undocumentedmatlab.com/blog/undocumented-hg2-graphics-events
I now have the following code:
%Updated to point to XRuler instead of just axes_handle
%per Yair's recommendation
obj.L3 = ...
addlistener(axes_handle.XRuler,'MarkedClean',@(~,~) obj.cleanListen);
end
function cleanListen(obj)
if isequal(obj.xlim,get(obj.axes_handle,'XLim'))
return
end
obj.listenerCallback();
It seems like MarkedClean is perhaps one of the ultimate 'Always tell me about things' events.
I'm not entirely sure what the answers to my questions are, but this serves as a decent workaround for what I need.
  댓글 수: 3
Jim Hokanson
Jim Hokanson 2017년 11월 27일
Thanks Yair. I'm not familiar with XRuler but a quick search turned up this info from your site:
http://undocumentedmatlab.com/blog/customizing-axes-rulers
Yair Altman
Yair Altman 2017년 11월 27일
of course, where else? :-)

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Adam Danz
Adam Danz 2021년 4월 15일
Starting in r2021a, you can supply a LimitsChangedFcn function the x-axes (or any of the x/y/z axes). This callback function overcomes the problems described with the XLim change event listener.
Specifically, the LimitsChangedFcn overcomes the problem mentioned by OP: "when I double-click to reset the zoom (or right click and reset) no listener is fired!"

카테고리

Help CenterFile Exchange에서 Timing and presenting 2D and 3D stimuli에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by