Свойство UIAxes YLim не может быть прослушано

MATLAB обеспечивает addlistener функция.

Слушатели позволяют нам отслеживать изменения свойств объекта и воздействовать на них. Например, мы можем создать очень простой слушатель, который будет отображать сообщение в командном окне, когда 'YLim' собственность axes объект изменен:

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

Попробуйте панорамировать оси или увеличить / уменьшить изображение и посмотреть, что произойдет. Это отлично работает.

Мне нужно сделать то же самое, но с помощью uiaxes вместо.

К сожалению, похоже, что нам запрещено это делать. Попробуйте запустить следующий пример:

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

Выдает эту ошибку:

Ошибка при использовании matlab.ui.control.UIAxes/addlistener При добавлении слушателя PostSet свойство 'YLim' в классе 'matlab.ui.control.UIAxes' не определено как SetObservable.

Я прочитал статьи Прослушайте изменения значений свойств и наблюдайте за изменениями значений свойств, и я узнал, что свойство должно быть объявлено как SetObservable чтобы быть услышанным:

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

Я пытался взглянуть на UIAxes определение класса через edit matlab.ui.control.UIAxes но это невозможно, потому что это P-файл.

Если 'YLim' тогда не наблюдается, как я могу отслеживать изменения в этом свойстве?

Я использую App Designer в MATLAB R2018b.

1 ответ

Решение

Мы должны прикрепить слушателя к внутреннему Axes объект, а не UIAxes сам. Попробуй это:

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

Если кому-то интересно, я нашел это методом проб и ошибок.

Протестировано на R2018a и R2018b.

Большое спасибо за это решение! У меня была реальная проблема с увеличением 3D-данных на UIAxes. Трехмерные оси содержали фоновую растровую карту.png при z=0 ( нанесенную на поверхность) и трехмерную позицию полета БПЛА в xyx. Когда я увеличивал масштаб, 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

Чувак, какая это была боль. Я рад, что теперь это работает. Еще раз спасибо.

Другие вопросы по тегам