UIAxes' YLim property cannot be listened to

為{幸葍}努か 提交于 2019-12-03 21:23:35

问题


MATLAB provides the addlistener function.

Listeners allow us to keep track of changes of an object's properties and act upon them. For example, we can create a very simple listener that will display a message in the command window when the 'YLim' property of an axes object is changed:

% Example using axes
ax = axes();
addlistener(ax, 'YLim', 'PostSet', @(src, evnt)disp('YLim changed'));

Try panning the axes or zooming in/out and see what happens. This works fine.

I need to do the same but using an uiaxes instead.

Unfortunately, it looks like we are not allowed to do so. Try running the following example:

% Example using uiaxes
ax = uiaxes();
addlistener(ax, 'YLim', 'PostSet', @(src, evnt)disp('YLim changed'));

It throws this error:

Error using matlab.ui.control.UIAxes/addlistener While adding a PostSet listener, property 'YLim' in class 'matlab.ui.control.UIAxes' is not defined to be SetObservable.

I've read the articles Listen for Changes to Property Values and Observe Changes to Property Values and I learned that a property must be declared as SetObservable to allow being listened:

classdef PropLis < handle
   properties (SetObservable)
      ObservedProp = 1 % <-- Observable Property
   end
end

I've tried taking a look at the UIAxes class definition via edit matlab.ui.control.UIAxes but it's not possible because it's a P-file.

If 'YLim' is not observable then how can I keep track of changes in this property?

I'm using App Designer in MATLAB R2018b.


回答1:


We should attach the listener to the internal Axes object, and not the UIAxes itself. Try this:

hFig = uifigure();
hAx = uiaxes(hFig);
addlistener(struct(hAx).Axes, 'YLim', 'PostSet', @(src, evnt)disp("YLim changed"));
hAx.YLim = [0 2];

In case anybody is wondering, I found this via trial and error.

Tested on R2018a & R2018b.




回答2:


Thank you so much for this solution! I was having a real problem with zooming in on 3D data on a UIAxes. The 3D axes contained a .png background raster map at z=0 (plotted as a surface) and the 3D position of a UAV flight in x-y-x. When I would zoom in, the z would zoom as well and the new z limits would exclude the map I wanted always displayed. What was odd, is that setting

app.UIAxes2.Interactions = [zoomInteraction('Dimensions','xy')];

would correct the problem when zooming with the scroll wheel on my mouse, but if I selected the zoom toolbar button (clicking to zoom), it would still zoom in z. Really frustrating.

To get around this, I used your example, but added the listener to the 'ZLim' and made a callback function that would look at all the elements of the plot, and reset ZLim to include all the data whenever the ZLim changed.

warning('off','MATLAB:structOnObject');
addlistener(struct(app.UIAxes2).Axes, 'ZLim', 'PostSet', @(src,evnt)mapholdaltlims(app,app.UIAxes2));


    function [inclusivezlim] = mapholdaltlims(app,ax)
        objwithz = findobj(app.UIAxes2.Children,'-property','ZData');
        currmin_z = 0;
        currmax_z = 0;
        for i = 1:length(objwithz)
            currmin_z = min([min(min(objwithz(i).ZData)), currmin_z]);%Need double mins because data could be 2d surface
            currmax_z = max([max(max(objwithz(i).ZData)), currmax_z]);
        end
        inclusivezlim = [currmin_z currmax_z];
        ax.ZLim = inclusivezlim;
        %disp('Updated the limits')
    end

Man, what a pain this was. I am glad it now works. Thanks again.



来源:https://stackoverflow.com/questions/53825151/uiaxes-ylim-property-cannot-be-listened-to

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!