exponenta event banner

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

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

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

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

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

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

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

  • 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 участвует в дорогостоящем расчете. 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.

См. также

Классы

Функции

Связанные темы