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

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

  • Initialize Property Values - Установите состояние по умолчанию компонента UI в случае, если ваши пользователи вызывают неявный конструктор без каких-либо входных параметров.

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

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

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

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

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

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

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

Для компонентов пользовательского интерфейса, которые содержат график и имеют свойства, которые хранят данные координат, установите начальные значения 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.

Можно также проверить свойства, которые хранят базовые объекты компонента в компоненте пользовательского интерфейса. Для этого необходимо знать правильное имя класса для каждого объекта. Чтобы определить имя класса объекта, вызовите соответствующую функцию компонента UI в командной строке, а затем вызовите class функция для получения имени класса. Например, если вы планируете создать раскрывающийся компонент в своем setup method, вызывать 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 значение. Это свойство указывает, изменились ли какие-либо свойства, используемые в дорогостоящем вычислении.

  • A 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 участвует в дорогостоящем расчете. The set.Prop2 метод устанавливает значение Prop2и затем устанавливает ExpensivePropChanged на true. В следующий раз, update метод запускается, он вызывает doExpensiveCalculation только если ExpensivePropChanged является true. Затем, update метод продолжает обновлять другие аспекты компонента UI.

Пример: Оптимизированная аппроксимация полиномом UI компонента с настроенным отображением свойств

Этот пример задает FitPlot класс для интерактивного отображения полиномов наилучшего полинома и использует все четыре из этих лучших практик. Свойства, заданные в блоке свойств, имеют значения по умолчанию и используют size и валидацию класса. The getPropertyGroups метод задает пользовательский порядок отображения свойств. The 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.

См. также

Классы

Функции

Похожие темы