Этот пример задает два класса:
fcneval
— Функциональный класс средства анализа содержит выражение MATLAB® и выполняет это выражение в заданной области значений
fcnview
— Функциональный класс средства просмотра содержит объект fcneval
и отображает поверхностные графики выполненного выражения с помощью данных, содержавшихся в fcneval
.
Этот класс задает два события:
Заданное классом событие, которое происходит, когда новое значение задано для функции MATLAB
Событие свойства, которое происходит, когда свойство, содержащее пределы, изменяется
Следующая схема показывает отношение между двумя объектами. Объект fcnview
содержит объект fcneval
и создает графики из данных, которые он содержит. fcnview
создает прослушиватели, чтобы изменить графики, если какие-либо из данных в объекте fcneval
изменяются.
Именование события в определении класса
Инициирование события путем вызова notify
Включение события свойства через атрибут SetObservable
Создание прослушивателей для заданных классом событий и событий свойства PostSet
Определение функций обратного вызова прослушивателя, которые принимают дополнительные аргументы
Включение и отключение прослушивателей
Класс fcneval
выполняет выражение MATLAB в заданной области значений двух переменных. fcneval
является источником данных что объекты графика класса fcnview
как поверхность. fcneval
является источником событий, используемых в этом примере. Для списка определения класса см. @fcneval/fcneval.m Код Класса
Свойство | Значение | Цель |
---|---|---|
FofXY | указатель на функцию | Выражение MATLAB (функция двух переменных). |
Lm | двухэлементный вектор | Пределы, по которым функция выполнена в обеих переменных. набор атрибута SetObservable к true , чтобы включить прослушиватели события свойства. |
Data | структура с x, y, и z матрицы | Данные, следующие из выполнения функции. Используемый для поверхностного графика. набор атрибута Dependent к true , что означает метод get.Data , называется, чтобы определить значение свойства, когда запрошено, и никакие данные не хранятся. |
Событие | Когда инициировано |
---|---|
UpdateGraph | Функция набора свойств FofXY (set.FofXY ) вызывает метод notify , когда новое значение задано для выражения MATLAB на объекте этого класса. |
Метод | Цель |
---|---|
fcneval | Конструктор класса. Входные параметры являются указателем на функцию и двухэлементным вектором, задающим пределы, по которым можно выполнить функцию. |
set.FofXY | Функция набора свойств FofXY . Названный каждый раз, когда значение свойства установлено, включая во время объектной конструкции. |
set.Lm | Функция набора свойств Lm . Используемый, чтобы протестировать на допустимые пределы. |
get.Data | Свойство Data получает функцию. Этот метод вычисляет значения для свойства Data каждый раз, когда те данные запрошены (членами класса или внешне). |
grid | Статический метод (набор атрибута Static к true ) используемый в вычислении данных. |
Объекты класса fcnview
содержат объекты fcneval
как источник данных для четырех поверхностных графиков, созданных в функциональном представлении. fcnview
создает прослушиватели и функции обратного вызова, которые отвечают на изменения в данных, содержавшихся в объектах fcneval
. Для списка определения класса см. @fcnview/fcnview.m Код Класса
Свойство | Значение | Цель |
---|---|---|
FcnObject | Объект fcneval | Этот объект содержит данные, которые используются, чтобы создать функциональные графики. |
HAxes | указатель осей | Каждый экземпляр fcnview объектно-ориентированная память указатель осей, содержащих его подграфик. |
HLUpdateGraph | Объект event.listener для события UpdateGraph | Установка свойства Enabled объекта event.listener к true включает прослушиватель; false отключает прослушиватель. |
HLLm | Объект event.listener для события свойства Lm | Установка свойства Enabled объекта event.listener к true включает прослушиватель, false отключает прослушиватель. |
HEnableCm | указатель uimenu | Элемент в контекстном меню раньше включал прослушиватели (раньше обрабатывал проверяемое поведение), |
HDisableCm | указатель uimenu | Элемент в контекстном меню раньше отключал прослушиватели (раньше управлял проверяемым поведением), |
HSurface | поверхностный указатель | Используемый коллбэками события, чтобы обновить поверхностные данные. |
Метод | Цель |
---|---|
fcnview | Конструктор класса. Вход является объектом fcneval . |
createLisn | Вызовы addlistener , чтобы создать прослушиватели для свойства UpdateGraph и Lm прослушиватели PostSet . |
lims | Устанавливает пределы осей к текущему значению свойства Lm объекта fcneval . Используемый обработчиками событий. |
updateSurfaceData | Обновляет поверхностные данные, не создавая новый объект. Используемый обработчиками событий. |
listenUpdateGraph | Коллбэк для события UpdateGraph . |
listenLm | Коллбэк для события PostSet свойства Lm |
delete | Удалите метод для класса fcnview . |
createViews | Статический метод, который создает экземпляр класса fcnview для каждого подграфика, задает контекстные меню, которые позволяют/запрещают прослушиватели, и создает подграфики |
И fcneval
и классы fcnview
наследовали методы от класса handle
. В следующей таблице перечислены только те унаследованные методы, используемые в этом примере.
Методы Класса Handle предоставляют полный список методов, которые наследованы, когда вы разделяете на подклассы класс handle
.
Методы, наследованные от класса Handle | Цель |
---|---|
addlistener | Укажите прослушиватель для определенного события и присоедините прослушиватель объекта event-defining. |
notify | Инициируйте событие и уведомите все зарегистрированные прослушиватели. |
Этот раздел объясняет, как использовать классы.
Создайте экземпляр класса fcneval
, чтобы содержать выражение MATLAB функции двух переменных и области значений, в которой вы хотите выполнить эту функцию
Используйте класс fcnview
статический функциональный createViews
, чтобы визуализировать функцию
Измените выражение MATLAB или пределы, содержавшие в объекте fcneval
, и все объекты fcnview
отвечают на сгенерированные события.
Вы создаете объект fcneval
путем вызова его конструктора с двумя аргументами — анонимная функция и двухэлементное, монотонно увеличения вектора. Например:
feobject = fcneval(@(x,y) x.*exp(-x.^2-y.^2),[-2 2]);
Используйте статический метод createViews
создать графики функции. Используйте имя класса, чтобы вызвать статическую функцию:
fcnview.createViews(feobject);
Метод createView
генерирует четыре представления функции, содержавшейся в объекте fcneval
.
Каждый подграфик задает контекстное меню, которое может включить и отключить прослушиватели, сопоставленные с тем графиком. Например, если вы отключаете прослушиватели на подграфике 221 (верхний левый угол) и изменяете выражение MATLAB, содержавшее в объекте fcneval
, только остающиеся три обновления подграфиков, когда событие UpdateGraph
инициировано:
feobject.FofXY = @(x,y) x.*exp(-x.^.5-y.^.5);
Точно так же, если вы изменяете пределы путем присвоения значения свойству feobject.Lm
, feobject
инициировал событие свойства PostSet
, и коллбэки прослушивателя обновляют график.
feobject.Lm = [-8 3];
В этой фигуре прослушиватели повторно включены через контекстное меню для подграфика 221. Поскольку коллбэк прослушивателя для события свойства PostSet
также обновляет поверхностные данные, все представления теперь синхронизируются
Событие UpdateGraph
имеет место, когда представление MATLAB математической функции, содержавшейся в объекте fcneval
, изменяется. Объекты fcnview
, которые содержат поверхностные графики, прислушиваются к этому событию, таким образом, они могут обновить графики, чтобы представлять новую функцию.
Событие UpdateGraph
является заданным классом событием. Имена классов fcneval
событие и вызовы notify
, когда событие имеет место.
Класс fcnview
задает прослушиватель для этого события. Когда fcneval
инициировал событие, прослушиватель fcnview
выполняет функцию обратного вызова, которая выполняет следовать действия:
Определяет, допустим ли указатель объекта подложки, хранившего объектом fcnview
все еще, (то есть, делает объект, все еще существуют),
Обновляет поверхностный XData
, YData
и ZData
путем запроса свойства Data
объекта fcneval
.
Класс fcneval
задает имя события в блоке event
:
events UpdateGraph end
Класс fcneval
задает метод набора свойств для свойства FofXY
. FofXY
является свойством, которое хранит выражение MATLAB для математической функции. Это выражение должно быть допустимым выражением MATLAB для функции двух переменных.
Метод set.FofXY
:
Определяет пригодность выражения
Если выражение подходит:
Присваивает выражение свойству FofXY
Инициировал событие UpdateGraph
Если fcneval.isSuitable
не возвращает объект MException
, метод set.FofXY
присваивает значение свойству и инициировал событие UpdateGraph
.
function set.FofXY(obj,func) % Determine if function is suitable to create a surface me = fcneval.isSuitable(func); if ~isempty(me) throw(me) end % Assign property value obj.FofXY = func; % Trigger UpdateGraph event notify(obj,'UpdateGraph'); end
Вызовы метода set.FofXY
статический метод (fcneval.isSuitable
), чтобы определить пригодность заданного выражения. fcneval.isSuitable
возвращает объект MException
, если он решает, что выражение является неподходящим. fcneval.isSuitable
вызывает конструктора MException
непосредственно, чтобы создать более полезные сообщения об ошибке для пользователя.
set.FofXY
выпускает исключение с помощью метода MException.throw
. Издание исключения отключает выполнение set.FofXY
и препятствует тому, чтобы метод делал присвоение на свойство или инициировал событие UpdateGraph
.
Вот метод fcneval.isSuitable
:
function isOk = isSuitable(funcH) v = [1 1;1 1]; % Can the expression except 2 numeric inputs try funcH(v,v); catch %#ok<CTCH> me = MException('DocExample:fcneval',... ['The function ',func2str(funcH),' Is not a suitable F(x,y)']); isOk = me; return end % Does the expression return non-scalar data if isscalar(funcH(v,v)); me = MException('DocExample:fcneval',... ['The function ',func2str(funcH),'' Returns a scalar when evaluated']); isOk = me; return end isOk = []; end
Метод fcneval.isSuitable
мог обеспечить дополнительный тест, чтобы гарантировать, что выражение, присвоенное свойству FofXY
, соответствует критериям, требуемым проектом класса.
Класс, возможно, реализовал событие набора свойств для свойства FofXY
и не должен будет, поэтому, вызывать notify
(см., Прислушиваются к Изменениям в Значениях свойств). Определение события класса обеспечивает больше гибкости в этом случае, потому что можно лучше управлять инициированием события.
Например, предположите, что вы хотели обновить график, только если новые данные отличаются. Если бы новое выражение произвело те же данные в некотором допуске, метод set.FofXY
не мог бы инициировать событие и постараться не обновлять график. Однако метод мог все еще установить свойство на новое значение.
Класс fcnview
создает прослушиватель для события UpdateGraph
с помощью метода addlistener
:
obj.HLUpdateGraph = addlistener(obj.FcnObject,'UpdateGraph',... @(src,evnt)listenUpdateGraph(obj,src,evnt)); % Add obj to argument list
Объектно-ориентированная память fcnview
указатель на объект event.listener
в его свойстве HLUpdateGraph
, которое используется, чтобы позволить/запретить прослушиватель контекстным меню (см., Включает и Отключает Прослушиватели).
Объект fcnview
(obj
) добавляется к этим двум параметрам по умолчанию (src
, evnt
) передал коллбэку прослушивателя. Следует иметь в виду, источник события (src
) является объектом fcneval
, но объект fcnview
содержит указатель объекта подложки, который обновляет коллбэк.
Функция listenUpdateGraph
задана можно следующим образом:
function listenUpdateGraph(obj,src,evnt) if ishandle(obj.HSurface) % If surface exists obj.updateSurfaceData % Update surface data end end
Функция updateSurfaceData
является методом класса, который обновляет поверхностные данные, когда различная математическая функция присвоена объекту fcneval
. Обновление данных о графическом объекте более эффективно, чем создание нового объекта с помощью новых данных:
function updateSurfaceData(obj) % Get data from fcneval object and set surface data set(obj.HSurface,... 'XData',obj.FcnObject.Data.X,... 'YData',obj.FcnObject.Data.Y,... 'ZData',obj.FcnObject.Data.Matrix); end
Все свойства поддерживают предопределенное событие PostSet
(См. События Набора свойств и Запроса для получения дополнительной информации о событиях свойства). Этот пример использует событие PostSet
для
свойства fcneval
Lm
. Это свойство содержит двухэлементный вектор, задающий область значений, в которой выполнена математическая функция. Сразу после того, как это свойство изменяется (оператором как obj.Lm = [-3 5];
), объекты fcnview
, прислушивающиеся к этому событию, обновляют график, чтобы отразить новые данные.
Последовательность во время присвоения свойства Lm
Класс fcneval
задает функцию множества для свойства Lm
. Когда значение присвоено этому свойству во время объектной конструкции или переназначения свойства, следующая последовательность происходит:
Попытка предпринята, чтобы присвоить значение аргумента свойству Lm
.
Метод set.Lm
выполняется, чтобы проверять, является ли значение в соответствующей области значений — если да, это делает присвоение, если не, это генерирует ошибку.
Если значение Lm
установлено успешно, MATLAB инициировал событие PostSet
.
Все прослушиватели выполняют свои коллбэки, но порядок недетерминирован.
Событие PostSet
не имеет место, пока фактическое присвоение свойства не происходит. Функция набора свойств обеспечивает возможность иметь дело с потенциальными ошибками присвоения, прежде чем событие PostSet
будет иметь место.
Чтобы создать прослушиватель для события PostSet
, необходимо установить атрибут SetObservable
свойства на true
:
properties (SetObservable = true) Lm = [-2*pi 2*pi]; % specifies default value end
MATLAB автоматически инициировал событие, таким образом, не необходимо вызвать notify
.
Укажите, что Атрибуты свойств предоставляют список всех атрибутов свойства.
Класс fcnview
создает прослушиватель для события PostSet
с помощью метода addlistener
:
obj.HLLm = addlistener(obj.FcnObject,'Lm','PostSet',... @(src,evnt)listenLm(obj,src,evnt)); % Add obj to argument list
Объектно-ориентированная память fcnview
указатель на объект event.listener
в его свойстве HLLm
, которое используется, чтобы позволить/запретить прослушиватель контекстным меню (см., Включает и Отключает Прослушиватели).
Объект fcnview
(obj
) добавляется к этим двум параметрам по умолчанию (src
, evnt
) передал коллбэку прослушивателя. Следует иметь в виду, источник события (src
) является объектом fcneval
, но объект fcnview
содержит указатель объекта подложки, который обновляет коллбэк.
Коллбэк устанавливает пределы осей и обновляет поверхностные данные, потому что изменение пределов заставляет математическую функцию быть оцененной в различной области значений:
function listenLm(obj,src,evnt) if ishandle(obj.HAxes) % If there is an axes lims(obj); % Update its limits if ishandle(obj.HSurface) % If there is a surface obj.updateSurfaceData % Update its data end end end
Каждый fcnview
объектно-ориентированная память указатель объектов прослушивателя, которые это создает так, чтобы прослушиватели могли быть включены или отключены через контекстное меню после графиков, создается. Все прослушиватели являются экземплярами класса event.listener
, который задает свойство под названием Enabled
. По умолчанию это свойство имеет значение true
, который включает прослушиватель. Если вы устанавливаете это свойство на false
, прослушиватель все еще существует, но отключен. Этот пример создает контекстное меню, активное на осях каждого графика, который обеспечивает способ изменить значение свойства Enabled
.
Существует два коллбэка, используемые контекстным меню, соответствующим этим двум элементам в меню:
Listen — Устанавливает свойство Enabled
и для UpdateGraph
и для прослушивателей PostSet
true
и добавляет галочку рядом с пунктом меню Listen.
Don't Listen — Устанавливает свойство Enabled
и для UpdateGraph
и для прослушивателей PostSet
false
и добавляет галочку рядом с пунктом меню Don't Listen.
Оба коллбэка включают объект fcnview
как аргумент (в дополнение к необходимому источнику и аргументам данных о событиях), чтобы обеспечить доступ к указателю объектов прослушивателя.
Функция enableLisn
вызвана, когда пользователь выбирает Listen из контекстного меню.
function enableLisn(obj,src,evnt) obj.HLUpdateGraph.Enabled = true; % Enable listener obj.HLLm.Enabled = true; % Enable listener set(obj.HEnableCm,'Checked','on') % Check Listen set(obj.HDisableCm,'Checked','off') % Uncheck Don't Listen end
Функция disableLisn
вызвана, когда пользователь выбирает Don't Listen из контекстного меню.
function disableLisn(obj,src,evnt) obj.HLUpdateGraph.Enabled = false; % Disable listener obj.HLLm.Enabled = false; % Disable listener set(obj.HEnableCm,'Checked','off') % Unheck Listen set(obj.HDisableCm,'Checked','on') % Check Don't Listen end
classdef fcneval < handle properties FofXY end properties (SetObservable = true) Lm = [-2*pi 2*pi] end % properties SetObservable = true properties (Dependent = true) Data end events UpdateGraph end methods function obj = fcneval(fcn_handle,limits) % Constructor returns object if nargin > 0 obj.FofXY = fcn_handle; % Assign property values obj.Lm = limits; end end function set.FofXY(obj,func) me = fcneval.isSuitable(func); if ~isempty(me) throw(me) end obj.FofXY = func; notify(obj,'UpdateGraph'); end function set.Lm(obj,lim) if ~(lim(1) < lim(2)) error('Limits must be monotonically increasing') else obj.Lm = lim; end end function data = get.Data(obj) [x,y] = fcneval.grid(obj.Lm); matrix = obj.FofXY(x,y); data.X = x; data.Y = y; data.Matrix = real(matrix); end end % methods methods (Static = true) function [x,y] = grid(lim) inc = (lim(2)-lim(1))/20; [x,y] = meshgrid(lim(1):inc:lim(2)); end % grid function isOk = isSuitable(funcH) v = [1 1;1 1]; try funcH(v,v); catch %#ok<CTCH> me = MException('DocExample:fcneval',... ['The function ',func2str(funcH),' Is not a suitable F(x,y)']); isOk = me; return end if isscalar(funcH(v,v)); me = MException('DocExample:fcneval',... ['The function ',func2str(funcH),' Returns a scalar when evaluated']); isOk = me; return end isOk = []; end end end
classdef fcnview < handle properties FcnObject % fcneval object HAxes % subplot axes handle HLUpdateGraph % UpdateGraph listener handle HLLm % Lm property PostSet listener handle HEnableCm % "Listen" context menu handle HDisableCm % "Don't Listen" context menu handle HSurface % Surface object handle end methods function obj = fcnview(fcnobj) if nargin > 0 obj.FcnObject = fcnobj; obj.createLisn; end end function createLisn(obj) obj.HLUpdateGraph = addlistener(obj.FcnObject,'UpdateGraph',... @(src,evnt)listenUpdateGraph(obj,src,evnt)); obj.HLLm = addlistener(obj.FcnObject,'Lm','PostSet',... @(src,evnt)listenLm(obj,src,evnt)); end function lims(obj) lmts = obj.FcnObject.Lm; set(obj.HAxes,'XLim',lmts); set(obj.HAxes,'Ylim',lmts); end function updateSurfaceData(obj) data = obj.FcnObject.Data; set(obj.HSurface,... 'XData',data.X,... 'YData',data.Y,... 'ZData',data.Matrix); end function listenUpdateGraph(obj,~,~) if ishandle(obj.HSurface) obj.updateSurfaceData end end function listenLm(obj,~,~) if ishandle(obj.HAxes) lims(obj); if ishandle(obj.HSurface) obj.updateSurfaceData end end end function delete(obj) if ishandle(obj.HAxes) delete(obj.HAxes); else return end end end methods (Static) createViews(a) end end
function createViews(fcnevalobj) p = pi; deg = 180/p; hfig = figure('Visible','off',... 'Toolbar','none'); for k=4:-1:1 fcnviewobj(k) = fcnview(fcnevalobj); axh = subplot(2,2,k); fcnviewobj(k).HAxes = axh; hcm(k) = uicontextmenu; set(axh,'Parent',hfig,... 'FontSize',8,... 'UIContextMenu',hcm(k)) fcnviewobj(k).HEnableCm = uimenu(hcm(k),... 'Label','Listen',... 'Checked','on',... 'Callback',@(src,evnt)enableLisn(fcnviewobj(k),src,evnt)); fcnviewobj(k).HDisableCm = uimenu(hcm(k),... 'Label','Don''t Listen',... 'Checked','off',... 'Callback',@(src,evnt)disableLisn(fcnviewobj(k),src,evnt)); az = p/k*deg; view(axh,az,30) title(axh,['View: ',num2str(az),' 30']) fcnviewobj(k).lims; surfLight(fcnviewobj(k),axh) end set(hfig,'Visible','on') end function surfLight(obj,axh) obj.HSurface = surface(obj.FcnObject.Data.X,... obj.FcnObject.Data.Y,... obj.FcnObject.Data.Matrix,... 'FaceColor',[.8 .8 0],'EdgeColor',[.3 .3 .2],... 'FaceLighting','phong',... 'FaceAlpha',.3,... 'HitTest','off',... 'Parent',axh); lims(obj) camlight left; material shiny; grid off colormap copper end function enableLisn(obj,~,~) obj.HLUpdateGraph.Enabled = true; obj.HLLm.Enabled = true; set(obj.HEnableCm,'Checked','on') set(obj.HDisableCm,'Checked','off') end function disableLisn(obj,~,~) obj.HLUpdateGraph.Enabled = false; obj.HLLm.Enabled = false; set(obj.HEnableCm,'Checked','off') set(obj.HDisableCm,'Checked','on') end