exponenta event banner

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

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

Начиная с R2020b, вместо сценария или функции можно создать реализацию класса для компонентов пользовательского интерфейса путем определения подкласса ComponentContainer базовый класс. Создание класса имеет следующие преимущества:

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

  • Инкапсуляция - организация кода таким образом позволяет скрыть сведения о реализации от пользователей. Реализуются методы, выполняющие вычисления и управляющие нижележащими графическими объектами.

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

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

В первой строке класса компонентов пользовательского интерфейса укажите matlab.ui.componentcontainer.ComponentContainer класс как суперкласс. Например, первая строка класса с именем ColorSelector выглядит следующим образом:

classdef ColorSelector < matlab.ui.componentcontainer.ComponentContainer

Помимо указания суперкласса, включите в определение класса следующие компоненты. Некоторые компоненты являются обязательными, а другие - рекомендуемыми или необязательными.

КомпонентОписание

Блок общедоступных свойств
рекомендуется

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

Блок частной собственности
рекомендуется

Этот блок определяет базовые графические объекты и другие сведения о реализации, к которым пользователи не могут получить доступ.

В этом блоке задайте следующие значения атрибутов:

  • Access = private

  • Transient

  • NonCopyable

Блок событий
(необязательно)

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

В этом блоке задайте следующие значения атрибутов:

  • HasCallbackProperty

  • NotifyAccess = protected

При установке HasCallbackProperty атрибут MATLAB ® создает открытое свойство для каждого события в блоке. Свойство public хранит предоставленный пользователем обратный вызов для выполнения при возникновении события.

setup метод
(обязательно)

Этот метод задает начальное состояние компонента пользовательского интерфейса. Он выполняется один раз, когда MATLAB создает объект.

Определите этот метод в защищенном блоке, чтобы его мог выполнять только класс.

update метод
(обязательно)

Этот метод обновляет базовые объекты в компоненте пользовательского интерфейса. Она выполняется при следующих условиях:

  • Во время следующего drawnow выполнение после изменения пользователем одного или нескольких значений свойств

  • Когда изменяется аспект графической среды пользователя (например, размер)

Определите этот метод в том же защищенном блоке, что и setup способ.

Метод конструктора

Нет необходимости писать метод конструктора для класса, поскольку он наследует его от ComponentContainer базовый класс. Унаследованный конструктор принимает необязательные входные аргументы: родительский контейнер и любое количество аргументов пары имя-значение для установки свойств компонента пользовательского интерфейса. Например, при определении класса с именем ColorSelector которая имеет общедоступные свойства Value и ValueChangedFcn, можно создать экземпляр класса, используя следующий код:

f = uifigure; 
c = ColorSelector(f,'Value',[1 1 0],'ValueChangedFcn',@(o,e)disp('Changed'))

Если требуется предоставить конструктор с другим синтаксисом или другим поведением, можно определить пользовательский метод конструктора. Пример пользовательского конструктора см. в разделе Запись конструкторов для классов диаграмм.

Блоки общедоступной и частной собственности

Разделите свойства класса как минимум между двумя блоками:

  • Открытый блок для хранения компонентов пользовательского интерфейса

  • Закрытый блок для хранения сведений о реализации, которые необходимо скрыть

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

Свойства, находящиеся в частном блоке, хранят базовые графические объекты, составляющие компонент пользовательского интерфейса, в дополнение к любым вычисленным значениям, которые необходимо сохранить. В конечном итоге класс будет использовать данные в общих свойствах для настройки базовых объектов. Установите Transient и NonCopyable атрибуты для частного блока, чтобы избежать хранения избыточной информации, если пользователь копирует или сохраняет экземпляр компонента пользовательского интерфейса.

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

properties
   Value {validateattributes(Value, ...
        {'double'},{'<=',1,'>=',0,'size',[1 3]})} = [1 0 0];   
end

properties(Access = private,Transient,NonCopyable)
   Grid matlab.ui.container.GridLayout 
   Button matlab.ui.control.Button 
   EditField matlab.ui.control.EditField
end   

Блок событий

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

Создайте общее свойство для каждого события в блоке, указав HasCallbackProperty атрибут. Свойство public хранит предоставленный пользователем обратный вызов для выполнения при возникновении события. Имя общедоступного свойства - это имя события, добавленное с буквами Fcn. Например, компонент пользовательского интерфейса, который позволяет пользователю выбрать значение цвета, может определить событие ValueChanged, который генерирует соответствующее публичное свойство ValueChangedFcn. Используйте notify метод для запуска события и выполнения обратного вызова в свойстве.

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

events (HasCallbackProperty, NotifyAccess = protected) 
   ValueChanged 
end 
Когда пользователь выбирает значение цвета, вызовите notify способ запуска ValueChanged и выполните обратный вызов в ValueChangedFcn собственность.
function getColorFromUser(obj)
    c = uisetcolor(obj.Value);
    if (isscalar(c) && (c == 0))
        return;
    end
    
    % Update the Value property
    oldValue = obj.Value;
    obj.Value = c;

    % Execute user callbacks and listeners
    notify(obj,'ValueChanged');
end
Когда пользователь создает экземпляр компонента пользовательского интерфейса, он может указать обратный вызов для выполнения при изменении значения цвета с помощью созданного общедоступного свойства.
f = uifigure; 
c = ColorSelector(f,'ValueChangedFcn',@(o,e)disp('Changed'))
Дополнительные сведения об указании обратных вызовов свойств см. в разделе Запись обратных вызовов для программных приложений.

Метод настройки

Определение setup метод для вашего класса. A setup выполняется один раз, когда MATLAB создает объект компонента пользовательского интерфейса. Любые значения свойств, переданные в качестве аргументов пары имя-значение методу конструктора, назначаются после выполнения этого метода.

Используйте setup метод для:

  • Создание графических объектов и объектов пользовательского интерфейса, составляющих компонент.

  • Сохраните объекты как частные свойства на объекте-компоненте.

  • Раскладывайте и конфигурируйте объекты.

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

Для обеспечения возможности выполнения только класса компонентов пользовательского интерфейса setup определить его в защищенном блоке.

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

Например, рассмотрим компонент пользовательского интерфейса, имеющий следующие свойства:

  • Одно общедоступное свойство с именем Value

  • Три именованных частных свойства Grid, Button, и EditField

setup метод вызывает uigridlayout, uieditfield, и uibutton для создания базового графического объекта для каждого частного свойства, указывающего экземпляр компонента пользовательского интерфейса (obj) в качестве целевого родителя.

function setup(obj) 
    % Create grid layout to manage building blocks 
    obj.Grid = uigridlayout(obj,[1 2],'ColumnWidth',{'1x',22},... 
       'RowHeight',{'fit'},'ColumnSpacing',2,'Padding',2); 

    % Create edit field for entering color value
    obj.EditField = uieditfield(obj.Grid,'Editable',false,... 
       'HorizontalAlignment','center'); 

    % Create button to confirm color change
    obj.Button = uibutton(obj.Grid,'Text',char(9998), ... 
       'ButtonPushedFcn',@(o,e) obj.getColorFromUser()); 
end 

Метод обновления

Определение update метод для вашего класса. Этот метод выполняется, когда объекту компонента пользовательского интерфейса необходимо изменить его внешний вид в ответ на изменение значений.

Используйте update метод для изменения конфигурации основных графических объектов в компоненте пользовательского интерфейса на основе новых значений общих свойств. Как правило, этот метод не определяет, какое из общих свойств было изменено. Он реконфигурирует все аспекты базовых графических объектов, которые зависят от общих свойств.

Например, рассмотрим компонент пользовательского интерфейса, имеющий следующие свойства:

  • Одно общедоступное свойство с именем Value

  • Три именованных частных свойства Grid, Button, и EditField

update метод обновляет BackgroundColor из EditField и Button объекты с цветом, сохраненным в Value. update метод также обновляет EditField с числовым представлением цвета. Однако таким образом Value изменяется, изменение становится одинаково заметным везде.

function update(obj)      
    % Update edit field and button colors 
    set([obj.EditField obj.Button],'BackgroundColor',obj.Value, ... 
       'FontColor',obj.getContrastingColor(obj.Value));  

    % Update edit field display text 
    obj.EditField.Value = num2str(obj.Value,'%0.2g ');            

end

Может возникнуть задержка между изменением значений свойств и просмотром результатов этих изменений. update метод запускается впервые после setup метод запускается, а затем запускается каждый раз drawnow выполняется. drawnow функция автоматически выполняется периодически, в зависимости от состояния графической среды в сеансе MATLAB пользователя. Это периодическое выполнение может привести к потенциальной задержке.

Пример: Компонент пользовательского интерфейса селектора цветов

В этом примере показано, как создать компонент пользовательского интерфейса для выбора цвета с использованием кода, описанного в других разделах этой страницы. Создание файла определения класса с именем ColorSelectorComponent.m в папке, расположенной по пути MATLAB. Определите класс, выполнив следующие действия.

ШагВнедрение

Вывести из ComponentContainer базовый класс.

classdef ColorSelector < matlab.ui.componentcontainer.ComponentContainer

Определение общих свойств.

    properties
        Value {validateattributes(Value, ...
            {'double'},{'<=',1,'>=',0,'size',[1 3]})} = [1 0 0]; 
    end

Определение публичных мероприятий.

    events (HasCallbackProperty, NotifyAccess = protected) 
        ValueChanged % ValueChangedFcn will be the generated callback property 
    end

Определите частные свойства.

    properties (Access = private, Transient, NonCopyable) 
        Grid matlab.ui.container.GridLayout 
        Button matlab.ui.control.Button 
        EditField matlab.ui.control.EditField 
    end

Реализация setup способ. В этом случае вызовите uigridlayout, uieditfield, и uibutton функции для создания GridLayout, EditField, и Button объекты. Сохраните эти объекты в соответствующих частных свойствах.

Укажите getColorFromUser метод в качестве ButtonPushedFcn обратный вызов, вызываемый при нажатии кнопки.

    methods (Access = protected) 
        function setup(obj) 
            % Grid layout to manage building blocks 
            obj.Grid = uigridlayout(obj,[1,2],'ColumnWidth',{'1x',22}, ... 
                'RowHeight',{'fit'},'ColumnSpacing',2,'Padding',2);              

            % Edit field for value display and button to launch uisetcolor 
            obj.EditField = uieditfield(obj.Grid,'Editable',false, ... 
                'HorizontalAlignment','center'); 
            obj.Button = uibutton(obj.Grid,'Text',char(9998), ... 
                'ButtonPushedFcn',@(o,e) obj.getColorFromUser()); 

        end 

Реализация update способ. В этом случае обновите цвет фона нижележащих объектов и текст в поле редактирования, чтобы показать значение цвета.

        function update(obj)     
            % Update edit field and button colors 
            set([obj.EditField obj.Button],'BackgroundColor',obj.Value, ... 
                'FontColor',obj.getContrastingColor(obj.Value));  

            % Update the display text 
            obj.EditField.Value = num2str(obj.Value,'%0.2g ');            
        end 
    end 

Соедините обратные вызовы и другие части с помощью частных методов.

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

Когда getContrastingColor метод вызывается update вычислите, является ли черный или белый текст более читаемым для нового цвета фона.

    methods (Access = private) 
        function getColorFromUser(obj) 
            c = uisetcolor(obj.Value); 
            if (isscalar(c) && (c == 0)) 
                return; 
            end 
            
            % Update the Value property 
            obj.Value = c;              

            % Execute user callbacks and listeners
            notify(obj,'ValueChanged'); 
        end         
        function contrastColor = getContrastingColor(~,color) 
            % Calculate opposite color 
            c = color * 255; 
            contrastColor = [1 1 1]; 
            if (c(1)*.299 + c(2)*.587 + c(3)*.114) > 186 
                contrastColor = [0 0 0]; 
            end 
        end 
    end 
end

Затем создайте экземпляр компонента пользовательского интерфейса, вызвав неявный метод конструктора с несколькими общими свойствами. Укажите обратный вызов для отображения слов Color changed при изменении значения цвета.

h = ColorSelector('Value', [1 1 0]); 
h.ValueChangedFcn = @(o,e) disp('Color changed');

Instance of the color selector UI component displaying the color yellow.

Нажмите кнопку и выберите цвет с помощью палитры цветов. Компонент изменяет внешний вид, и MATLAB отображает слова Color changed в окне команд.

Instance of the color selector UI component displaying the color blue.

См. также

Классы

Функции

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