Этот пример задает два класса:
fcneval
- Класс вычислителя функции содержит MATLAB® выражение и оценивает это выражение по заданной области
fcnview
- Класс средство просмотра содержит fcneval
объект и отображает поверхностные графики вычисленного выражения с использованием данных, содержащихся в fcneval
.
Этот класс задает два события:
Определяемое классом событие, которое происходит, когда для функции MATLAB задано новое значение
Событие свойства, которое происходит, когда свойство, содержащее пределы, изменено
Следующая схема показывает связь между этими двумя объектами. The fcnview
объект содержит fcneval
объект и создает графики из содержащихся в нем данных. fcnview
создает прослушиватели, чтобы изменить графики, если какие-либо из данных в fcneval
изменение объекта.
Присвоение имени событию в определении класса
Запуск события вызовом notify
Включение события свойства через SetObservable
признак
Создание прослушивателей для определяемых классами событий и PostSet
свойств события
Определение функций обратного вызова прослушивателя, которые принимают дополнительные аргументы
Включение и отключение прослушивателей
The fcneval
класс вычисляет выражение MATLAB для заданной области двух переменных. The 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 событие | Установка event.listener Enabled объекта свойство к true включает прослушиватель; false отключает прослушиватель. |
HLLm | event.listener объект для Lm событие свойства | Установка event.listener Enabled объекта свойство к true включает прослушиватель, false отключает прослушиватель. |
HEnableCm | uimenu указателя | Элемент контекстного меню, используемый для включения прослушивателей (используется для обработки проверенного поведения) |
HDisableCm | uimenu указателя | Элемент контекстного меню, используемый для отключения прослушивателей (используется для управления проверенным поведением) |
HSurface | поверхностный указатель | Используется коллбэками событий для обновления данных о поверхности. |
Метод | Цель |
---|---|
fcnview | Конструктор классов. Вход fcneval объект. |
createLisn | Вызовы addlistener чтобы создать прослушиватели для UpdateGraph и Lm свойства PostSet прослушиватели. |
lims | Устанавливает пределы осей к текущему значению fcneval Lm объекта свойство. Используется обработчиками событий. |
updateSurfaceData | Обновление данных поверхности без создания нового объекта. Используется обработчиками событий. |
listenUpdateGraph | Коллбэк для UpdateGraph событие. |
listenLm | Коллбэк для Lm свойства PostSet событие |
delete | Удалите метод для fcnview класс. |
createViews | Статический метод, который создает образец fcnview класс для каждого подграфика, определяет контекстные меню, которые включают/отключают прослушиватели, и создает подграфики |
Оба fcneval
и fcnview
классы наследуют методы от handle
класс. В следующей таблице перечислены только те унаследованные методы, которые используются в этом примере.
Handle Class Methods предоставляет полный список методов, которые наследуются при подклассификации handle
класс.
Методы, унаследованные от класса Handle | Цель |
---|---|
addlistener | Зарегистрируйте прослушиватель для определенного события и присоедините прослушивателя к определяющему событие объекту. |
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);
The 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
событие также обновляет данные поверхности, теперь синхронизируются все представления
The UpdateGraph
событие происходит, когда представление MATLAB математической функции, содержащейся в fcneval
объект изменяется. The fcnview
объекты, которые содержат графики, прослушивают это событие, поэтому они могут обновить графики, чтобы представлять новую функцию.
The UpdateGraph
событие является событием, заданным классом. The fcneval
класс называет событие и вызовы notify
когда происходит событие.
The fcnview
класс задает прослушиватель для этого события. Когда fcneval
запускает событие, fcnview
прослушиватель выполняет функцию обратного вызова, которая выполняет следующие действия:
Определяет, хранится ли указатель на объект поверхности в fcnview
объект все еще действителен (то есть объект все еще существует)
Обновление поверхностного XData
, YData
, и ZData
путем запроса fcneval
Data
объекта свойство.
The fcneval
класс задает имя события в event
блок:
events UpdateGraph end
The fcneval
класс определяет метод набора свойств для FofXY
свойство. FofXY
- свойство, которое хранит выражение MATLAB для математической функции. Это выражение должно быть допустимым выражением MATLAB для функции двух переменных.
The 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
The set.FofXY
метод вызывает статический метод (fcneval.isSuitable
) для определения пригодности указанного выражения. fcneval.isSuitable
возвращает MException
объект, если он определяет, что выражение непригодно. fcneval.isSuitable
вызывает MException
конструктор непосредственно для создания более полезных сообщений об ошибке для пользователя.
set.FofXY
выдает исключение с помощью 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
The fcneval.isSuitable
метод может обеспечить дополнительный тест, чтобы убедиться, что выражение, назначенное FofXY
свойство соответствует критериям, необходимым для проекта класса.
Класс мог реализовать событие набора свойств для FofXY
свойство и, следовательно, не нужно было звонить notify
(см. «Прослушивание изменений значений свойств»). Определение события класса обеспечивает большую гибкость в этом случае, потому что вы можете лучше управлять срабатыванием события.
Например, предположим, что вы хотели обновить график, только если новые данные отличаются. Если новое выражение дало те же данные в пределах некоторого допуска, set.FofXY
метод не смог вызвать событие и избежать обновления графика. Однако метод все еще может задать новое значение свойства.
The fcnview
класс создает прослушиватель для UpdateGraph
событием с использованием addlistener
метод:
obj.HLUpdateGraph = addlistener(obj.FcnObject,'UpdateGraph',... @(src,evnt)listenUpdateGraph(obj,src,evnt)); % Add obj to argument list
The fcnview
объект хранит указатель на event.listener
объект в своем HLUpdateGraph
свойство, которое используется для включения/отключения прослушивателя контекстным меню (см. «Включение и отключение прослушивателей»).
The fcnview
объект (obj
) добавляется к двум аргументам по умолчанию (src
, evnt
) передан в обратный коллбэк прослушивателя. Имейте в виду, источник события (src
) является fcneval
объект, но fcnview
объект содержит указатель на объект поверхности, который обновляется коллбэком.
The listenUpdateGraph
функция определяется следующим образом:
function listenUpdateGraph(obj,src,evnt) if ishandle(obj.HSurface) % If surface exists obj.updateSurfaceData % Update surface data end end
The 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
событие (для получения дополнительной информации о событиях свойств см. раздел Property-Set и Query Events). Этот пример использует PostSet
событие для fcneval
Lm
свойство. Это свойство содержит двухэлементный вектор, задающий область значений, в котором вычисляется математическая функция. Сразу после того, как это свойство будет изменено (оператором like obj.Lm = [-3 5];
), а fcnview
объекты, прослушивающие это событие, обновляют график, чтобы отразить новые данные.
Lm
Назначение свойствThe fcneval
класс определяет функцию набора для Lm
свойство. Когда значение присваивается этому свойству во время конструкции объекта или переназначения свойства, происходит следующая последовательность:
Делается попытка присвоить значение аргумента Lm
свойство.
The set.Lm
метод выполняется, чтобы проверить, находится ли значение в соответствующей области значений - если да, это делает назначение, если нет, это генерирует ошибку.
Если значение Lm
успешно установлен, MATLAB запускает PostSet
событие.
Все прослушиватели выполняют свои коллбэки, но порядок недетерминирован.
The PostSet
событие не происходит до тех пор, пока не произойдет фактическое присвоение свойства. Функция набора свойств предоставляет возможность справиться с потенциальными ошибками назначения перед PostSet
происходит событие.
Чтобы создать прослушиватель для PostSet
событие, необходимо задать SetObservable
свойства атрибут к
true
:
properties (SetObservable = true) Lm = [-2*pi 2*pi]; % specifies default value end
MATLAB автоматически запускает событие, поэтому нет необходимости в вызове notify
.
Параметр «Задать атрибуты свойств» содержит список всех атрибутов свойств.
The fcnview
класс создает прослушиватель для PostSet
событием с использованием addlistener
метод:
obj.HLLm = addlistener(obj.FcnObject,'Lm','PostSet',... @(src,evnt)listenLm(obj,src,evnt)); % Add obj to argument list
The fcnview
объект хранит указатель на event.listener
объект в своем HLLm
свойство, которое используется для включения/отключения прослушивателя контекстным меню (см. «Включение и отключение прослушивателей»).
The 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
объект как аргумент (в дополнение к требуемым аргументам source и event data) для предоставления доступа к указателю на объекты прослушивателя.
The 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
The 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