Управляйте свойствами пользовательских компонентов пользовательского интерфейса

Когда вы разрабатываете пользовательский компонент пользовательского интерфейса как подкласс ComponentContainer базовый класс, можно использовать определенные методы, чтобы сделать код более устойчивым, эффективным, и удобным для пользователя. Это особое внимание методов о том, как вы задаете и управляете свойствами своего класса. Используйте любого, которые полезны для типа компонента, который вы хотите создать и пользовательский опыт, который вы хотите обеспечить.

  • Инициализируйте Значения свойств — Набор состояние по умолчанию компонента пользовательского интерфейса в случае, если ваши пользователи вызывают неявного конструктора без любых входных параметров.

  • Проверка значений свойств — Убедитесь, что значения допустимы перед использованием их.

  • Настройте Отображение Свойства — Предоставляют индивидуально настраиваемый список свойств в Командном окне когда справочники пользователя объект компонента пользовательского интерфейса без точки с запятой.

  • Оптимизируйте Метод обновления — Улучшают производительность update метод, когда только подмножество ваших свойств используются в длительном вычислении.

Для примера этих методов смотрите Пример: Оптимизированная Аппроксимация полиномом Компонент пользовательского интерфейса с Индивидуально настраиваемым Отображением Свойства.

Кроме того, существуют определенные факторы и ограничения, чтобы иметь в виду, хотите ли вы использовать свой пользовательский компонент пользовательского интерфейса в App Designer или совместно использовать ваш компонент с пользователями, которые разрабатывают приложения в App Designer. Эти факторы перечислены на отдельной странице, в Конфигурируют Пользовательские Компоненты пользовательского интерфейса для App Designer.

Инициализация значений свойств

Присвойте значения по умолчанию для всех публичных свойств вашего класса. Это позволяет MATLAB создавать допустимый компонент пользовательского интерфейса, даже если пользователь не использует некоторые аргументы name-value, когда они вызывают метод конструктора.

Для компонентов пользовательского интерфейса, которые содержат график и имеют свойства, которые хранят координатные данные, установите начальные значения к NaN значения или пустые массивы так, чтобы график по умолчанию был пуст, когда пользователь не задает координаты.

Проверка значений свойств

Прежде чем ваш код использует значения свойств, подтвердите, что у них есть правильный размер и класс. Например, этот блок свойства подтверждает размер и класс трех свойств.

properties
    LineColor {validateattributes(LineColor,{'double'}, ... 
        {'<=',1,'>=',0,'size',[1 3]})} = [1 0 0]
    XData (1,:) double = NaN
    YData (1,:) double = NaN
end

LineColor должен быть 1 3 массив класса double, где каждое значение находится в области значений [0,1]. Оба XData и YData должны быть векторы-строки из класса double.

Можно также подтвердить свойства, которые хранят базовые объекты компонента в компоненте пользовательского интерфейса. Для этого необходимо знать правильное имя класса для каждого объекта. Чтобы определить имя класса объекта, вызовите соответствующую функцию компонента пользовательского интерфейса в командной строке, и затем вызовите class функция, чтобы получить имя класса. Например, если вы планируете создать выпадающий компонент в своем setup метод, вызовите uidropdown функция в командной строке с выходным аргументом. Затем передайте выход class функция, чтобы получить ее имя класса.

dd = uidropdown;
class(d)
ans =

    'matlab.ui.control.DropDown'

Используйте выход class функция, чтобы подтвердить класс для соответствующего свойства в вашем классе. Задайте класс после имени свойства. Например, следующее свойство хранит DropDown возразите и подтверждает его класс.

properties (Access = private, Transient, NonCopyable)
        DropDown matlab.ui.control.DropDown
end

Иногда, вы можете хотеть задать свойство, которое может сохранить различные формы и классы значений. Например, если вы задаете свойство, которое может сохранить вектор символов, массив ячеек из символьных векторов, или массив строк, не использовать размер и валидацию класса или использовать пользовательский метод валидации свойства. Для получения дополнительной информации о проверке свойств, см. Проверку значений свойств.

Настройте отображение свойства

Одно из преимуществ определения вашего компонента пользовательского интерфейса как подкласс ComponentContainer базовый класс - то, что это также наследовалось matlab.mixin.CustomDisplay класс. Это позволяет вам настроить список свойств MATLAB® отображения в Командном окне, когда вы ссылаетесь на компонент пользовательского интерфейса без точки с запятой. Чтобы настроить отображение свойства, перегрузите getPropertyGroups метод. В рамках того метода можно настроить, какие свойства перечислены и порядок списка. Например, рассмотрите FitPlot класс, который имеет следующие публичные свойства.

properties
    LineColor {validateattributes(LineColor,{'double'}, ... 
        {'<=',1,'>=',0,'size',[1 3]})} = [1 0 0]
    XData (1,:) double = NaN
    YData (1,:) double = NaN
end

Следующий getPropertyGroups метод задает скалярный список свойств объекта как XData, YData, и LineColor.

function propgrp = getPropertyGroups(obj)
    if ~isscalar(obj)
        % List for array of objects
        propgrp = getPropertyGroups@matlab.mixin.CustomDisplay(obj);    
    else
        % List for scalar object
        propList = {'XData','YData','LineColor'};
        propgrp = matlab.mixin.util.PropertyGroup(propList);
    end
end

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

p = FitPlot
p = 

  FitPlot with properties:

    XData: NaN
    YData: NaN
    LineColor: [1 0 0]

Для получения дополнительной информации о настройке отображения свойства, см. Отображение пользовательских свойств.

Оптимизируйте update Метод

В большинстве случаев, update метод вашего класса реконфигурировал все соответствующие аспекты вашего компонента пользовательского интерфейса, которые зависят от публичных свойств. Иногда, реконфигурирование включает дорогое вычисление, которое является трудоемким. Если вычисление включает только подмножество свойств, можно спроектировать класс, чтобы выполнить тот код только, когда это необходимо.

Один способ оптимизировать update метод должен добавить эти элементы в ваш класс:

  • Частная собственность под названием ExpensivePropChanged это принимает logical значение. Это свойство указывает, изменилось ли какое-либо из свойств, используемых в дорогом вычислении.

  • set метод для каждого свойства, вовлеченного в дорогое вычисление. В каждом set метод, набор ExpensivePropChanged свойство к true.

  • Защищенный метод под названием doExpensiveCalculation это выполняет дорогое вычисление.

  • Условный оператор в update метод, который проверяет значение ExpensivePropChanged. Если значением является true, выполните doExpensiveCalculation.

Следующий код предоставляет шаблон для этого проекта.

classdef OptimizedUIComponent <  matlab.ui.componentcontainer.ComponentContainer
    
    properties
        Prop1
        Prop2
    end
    properties(Access=private,Transient,NonCopyable)
        ExpensivePropChanged (1,1) logical = true
    end
    
    methods(Access = protected)
        function setup(obj)
            % Configure UI component
            % ...
        end
        function update( obj )
            % Perform expensive computation if needed
            if obj.ExpensivePropChanged
                doExpensiveCalculation(obj);
                obj.ExpensivePropChanged = false;
            end
            
            % Update other aspects of UI component
            % ...
        end
        function doExpensiveCalculation(obj)
            % Expensive code
            % ...
        end
    end
    
    methods
        function set.Prop2(obj,val)
            obj.Prop2 = val;
            obj.ExpensivePropChanged = true;
        end
    end
end

В этом случае, Prop2 вовлечен в дорогое вычисление. set.Prop2 метод устанавливает значение Prop2, и затем это устанавливает ExpensivePropChanged к true. В следующий раз update запуски метода, это вызывает doExpensiveCalculation только если ExpensivePropChanged true. Затем update метод продолжает обновлять другие аспекты компонента пользовательского интерфейса.

Пример: оптимизированная аппроксимация полиномом компонент пользовательского интерфейса с индивидуально настраиваемым отображением свойства

Этот пример задает FitPlot класс для того, чтобы в интерактивном режиме отобразить лучшие подходящие полиномы и использование все четыре из этих лучших практик. Свойства, заданные в блоке свойств, имеют значения по умолчанию и используют валидация класса и размер. getPropertyGroups метод задает пользовательский порядок для отображения свойства. changeFit метод выполняет потенциально дорогое вычисление аппроксимации полиномом и update метод выполняет changeFit только если отображенные на графике измененные данные.

Чтобы задать этот класс, сохраните FitPlot определение класса в файл с именем FitPlot.m в папке, которая находится на пути MATLAB.

classdef FitPlot < matlab.ui.componentcontainer.ComponentContainer
    % Choose a fit method for your plotted data
    
    properties
        LineColor {validateattributes(LineColor,{'double'}, ... 
            {'<=',1,'>=',0,'size',[1 3]})} = [1 0 0]
        XData (1,:) double = NaN
        YData (1,:) double = NaN
    end

    properties (Access = private, Transient, NonCopyable)
        DropDown matlab.ui.control.DropDown
        Axes matlab.ui.control.UIAxes
        GridLayout matlab.ui.container.GridLayout
        DataLine (1,1) matlab.graphics.chart.primitive.Line
        FitLine (1,1) matlab.graphics.chart.primitive.Line
        FitXData (1,:) double
        FitYData (1,:) double 
        ExpensivePropChanged (1,1) logical = true
    end
    
    methods (Access=protected)
        function setup(obj)
            % Set the initial position of this component
            obj.Position = [100 100 300 300];
            
            % Create the grid layout, drop-down, and axes
            obj.GridLayout = uigridlayout(obj,[2,1], ...
                'RowHeight',{20,'1x'},...
                'ColumnWidth',{'1x'});
            obj.DropDown = uidropdown(obj.GridLayout, ...
                'Items',{'None','Linear','Quadratic','Cubic'}, ...
                'ValueChangedFcn',@(s,e) changeFit(obj));
            obj.Axes = uiaxes(obj.GridLayout);
             
            % Create the line objects
            obj.DataLine = plot(obj.Axes,NaN,NaN,'o');
            hold(obj.Axes,'on');
            obj.FitLine = plot(obj.Axes,NaN,NaN);
            hold(obj.Axes,'off');
        end
        
        function update(obj)
            % Update data points
            obj.DataLine.XData = obj.XData;
            obj.DataLine.YData = obj.YData;
            
            % Do an expensive operation
            if obj.ExpensivePropChanged
                obj.changeFit();
                obj.ExpensivePropChanged = false;
            end
            
            % Update the fit line
            obj.FitLine.Color = obj.LineColor;
            obj.FitLine.XData = obj.FitXData;
            obj.FitLine.YData = obj.FitYData;
        end
        
        function changeFit(obj)
            % Calculate the fit line based on the drop-down value
            if strcmp(obj.DropDown.Value,'None')
                obj.FitXData = NaN;
                obj.FitYData = NaN;
            else
                switch obj.DropDown.Value
                    case 'Linear'
                        f = polyfit(obj.XData,obj.YData,1);
                    case 'Quadratic'
                        f = polyfit(obj.XData,obj.YData,2);
                    case 'Cubic'
                        f = polyfit(obj.XData,obj.YData,3);
                end
                obj.FitXData = linspace(min(obj.XData),max(obj.XData));
                obj.FitYData = polyval(f,obj.FitXData);
            end
        end
        
        function propgrp = getPropertyGroups(obj)
            if ~isscalar(obj)
                % List for array of objects
                propgrp = getPropertyGroups@matlab.mixin.CustomDisplay(obj);    
            else
                % List for scalar object
                propList = {'XData','YData','LineColor'};
                propgrp = matlab.mixin.util.PropertyGroup(propList);
            end
        end

    end
    
    methods
        function set.XData(obj,val)
            obj.XData = val;
            obj.ExpensivePropChanged = true;
        end
        function set.YData(obj,val)
            obj.YData = val;
            obj.ExpensivePropChanged = true;
        end
    end
end

Задайте некоторые выборочные данные и используйте их, чтобы создать экземпляр FitPlot.

x = [0 0.3 0.8 1.1 1.6 2.3];
y = [0.6 0.67 1.01 1.35 1.47 1.25];
p = FitPlot('XData',x,'YData',y)
ans = 

  FitPlot with properties:

        XData: [1×43 double]
        YData: [1×43 double]
    LineColor: [1 0 0]

Instance of the FitPlot class displaying a drop-down with the value 'None' and an axes with some sample data.

Используйте выпадающее, чтобы отобразить квадратичную лучшую подходящую кривую.

Instance of the FitPlot class. The drop-down is expanded the mouse pointer is on the "Quadratic" option. The axes shows sample data and a red quadratic line of best fit.

Установите LineColor свойство изменить цвет лучшей подходящей кривой к зеленому.

p.LineColor = [0 0.5 0];

Instance of the FitPlot class. The drop-down value is "Quadratic" and the axes show sample data and a green quadratic line of best fit.

Смотрите также

Классы

Функции

Похожие темы