无法收听 UIAxes 的 YLim 属性

UIAxes' YLim property cannot be listened to

MATLAB 提供 addlistener 函数。

侦听器使我们能够跟踪对象属性的变化并根据它们采取行动。例如,我们可以创建一个非常简单的侦听器,当 axes 对象的 'YLim' 属性 发生变化时,它将在命令 window 中显示一条消息:

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

尝试平移轴或缩放 in/out 看看会发生什么。这很好用。

我需要做同样的事情,但使用 uiaxes 代替。

很遗憾,我们似乎不被允许这样做。尝试 运行 以下示例:

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

它抛出这个错误:

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.

我读过文章 Listen for Changes to Property Values and Observe Changes to Property Values 并且我了解到必须将 属性 声明为 SetObservable 才能被收听:

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

我试过通过 edit matlab.ui.control.UIAxes 查看 UIAxes class 的定义,但这是不可能的,因为它是 P-file.

如果 'YLim' 不可观察,那么我如何跟踪此 属性 中的变化?

我在 MATLAB R2018b 中使用 App Designer

我们应该将侦听器附加到内部 Axes 对象,而不是 UIAxes 本身。试试这个:

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

如果有人想知道,我是通过反复试验发现的。

在 R2018a 和 R2018b 上测试。

非常感谢您提供此解决方案!在 UIAxes 上放大 3D 数据时我遇到了一个真正的问题。 3D 轴包含 z=0 (plotted as a surface) 处的 .png 背景栅格地图和 x-y-x 中无人机飞行的 3D 位置。当我放大时,z 也会缩放,新的 z 限制会排除我想要始终显示的地图。奇怪的是,设置

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

使用鼠标上的滚轮进行缩放时会解决此问题,但如果我选择缩放工具栏按钮(单击缩放),它仍会放大 z。真令人沮丧。

为了解决这个问题,我使用了您的示例,但将侦听器添加到 'ZLim' 并创建了一个回调函数来查看绘图的所有元素,并重置 ZLim 以包含所有数据每当 ZLim 改变时。

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

伙计,这是多么痛苦啊。我很高兴它现在可以工作了。再次感谢。