- 在线时间
- 1084 小时
- 最后登录
- 2015-9-10
- 注册时间
- 2014-4-18
- 听众数
- 162
- 收听数
- 1
- 能力
- 10 分
- 体力
- 43976 点
- 威望
- 6 点
- 阅读权限
- 255
- 积分
- 15250
- 相册
- 0
- 日志
- 0
- 记录
- 1
- 帖子
- 3471
- 主题
- 2620
- 精华
- 1
- 分享
- 0
- 好友
- 513
升级   0% TA的每日心情 | 开心 2015-3-12 15:35 |
---|
签到天数: 207 天 [LV.7]常住居民III
 群组: 第六届国赛赛前冲刺培 群组: 国赛讨论 群组: 2014美赛讨论 群组: 2014研究生数学建模竞 群组: 数学中国试看培训视频 |
前面介绍了MATLAB中事件模型的基本原理和设计方法。下面通过一个完整的实例来实现事件模型的具体设计过程。
例8-2 建立一个图形用户界面,要求:
(1)在界面上用subplot命令绘制两个坐标轴,在每个坐标轴上各绘制一个曲面;
(2)利用函数的变化和函数区间的变化来触发件,通过事件来及时更新函数图形的绘制;
(3)通过上下文菜单来设置各个坐标轴是否收听事件。
分析:在本例中涉及到两个事件来对应函数变化情况和自变量区间变化情况。函数的变化情况可以在events块中定义一个普通的事件UpdateGraphics来描述,而函数区间的变化情况可以采用PostSet事件来设置。这样,就需要定义两个听众来响应这两个事件。利用听众的Enabled特性来设置是否收听这些事件。
解:为解决本例问题,需要设计两个类,一个是函数运算类MfunEval,在这个类中定义一个函数句柄hFun和区间变量Lm,并在其中events块中定义一个UpdateGraph事件,另一个是坐标轴类Maxes,在其中定义两个听众对象,并与相应的回调函数相关联实现绘图更新。
本实例文件目录结构如图8-2所示。
文件MFunEval.m中的代码为:
classdef MFunEval< handle %函数计算类
properties
hFun %函数句柄
end
properties (SetObservable = true)
Lm = []; %区间
end
properties (Dependent = true)
Data %保存网格化数据
end
events
UpdateGraph %更新图形
end
methods
function obj = MFunEval(fcn_handle,limits) %构造函数
obj.hFun = fcn_handle;
obj.Lm = limits;
end
function fofxy = set.hFun(obj,func)
obj.hFun = func;
notify(obj,'UpdateGraph'); %广播事件
end
function data = get.Data(obj) %获取网格化数据
[x,y] = MFunEval.grid(obj.Lm);
matrix = obj.hFun(x,y);
data.X = x;
data.Y = y;
data.Matrix = matrix;
end
end
methods (Static)
function [x,y] = grid(lim) %网格化
inc = (lim(2)-lim(1))/20;
[x,y] = meshgrid(lim(1):inc:lim(2));
end
end
end
复制代码
文件MAxes.m中的代码为:
classdef MAxes < handle %坐标轴类
properties
FunObject = [] %函数计算类对象
hLUpdateGraph = [] %图形更新听众句柄
hLLm = [] %区间Lm的PostSet事件听众句柄
hEnableCm = [] %上下文菜单“Listen”句柄
hDisableCm = [] %上下文菜单“Don't Listen”句柄
hAxes = []; %坐标轴句柄
hSurface = [] %曲面对象句柄
end
methods
function obj= MAxes(funobj)
obj.FunObject = funobj;
obj.CreateLisn; %创建听众
end
function CreateLisn(obj) %创建两个听众
obj.hLUpdateGraph = addlistener(obj.FunObject,'UpdateGraph',...
@(src,evnt)listenUpdateGraph(obj,src,evnt));
obj.hLLm = addlistener(obj.FunObject,'Lm','PostSet',...
@(src,evnt)listenLm(obj,src,evnt));
end
%听众1的回调函数
function listenUpdateGraph(obj,src,evnt) %更新图形
if ishandle(obj.hSurface)
obj.updateSurfaceData
end
end
function updateSurfaceData(obj)
data = obj.FunObject.Data;
set(obj.hSurface,...
'XData',data.X,...
'YData',data.Y,...
'ZData',data.Matrix);
end
%听众2的回调函数
function listenLm(obj,src,evnt)
if ishandle(obj.hAxes)
lims(obj);
if ishandle(obj.hSurface)
obj.updateSurfaceData
end
end
end
function lims(obj)
lmts = obj.FunObject.Lm;
set(obj.hAxes,'XLim',lmts);
set(obj.hAxes,'Ylim',lmts);
end
function delete(obj) %析构函数
if ishandle(obj.hAxes)
delete(obj.hAxes);
else
return
end
end
end
methods (Static = true)
function CreateViews(funobj) %绘制曲面
hFigure = figure('Name','利用事件模型更新图', 'Toolbar','none');
for k=1:2
axesobj(k)= MAxes(funobj); %定义坐标轴对象
axh=subplot(1,2,k);
axesobj(k).hAxes=axh;
hcm(k)=uicontextmenu; %上下文菜单
set(axesobj(k).hAxes,'Parent',hFigure,...
'FontSize',8,...
'UIContextMenu',hcm(k));
axesobj(k).hEnableCm = uimenu(hcm(k),...
'Label','Listen',...
'Checked','on',...
'Callback',...
@(src,evnt)enableLisn(axesobj,src,evnt));
axesobj(k).hDisableCm = uimenu(hcm(k),...
'Label','Don''t Listen',...
'Checked','off',...
'Callback',...
@(src,evnt)disableLisn(axesobj(k),src,evnt));
view(axesobj(k).hAxes,60,30)
axesobj(k).lims;
surfLight(axesobj(k),axesobj(k).hAxes); %绘制曲面
end
end
end
end
复制代码
以下是三个全局函数:
function surfLight(obj,axh)
obj.hSurface = surface(obj.FunObject.Data.X,...
obj.FunObject.Data.Y,...
obj.FunObject.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,src,evnt)
obj.hLUpdateGraph.Enabled = true;
obj.hLLm.Enabled = true;
set(obj.hEnableCm,'Checked','on')
set(obj.hDisableCm,'Checked','off')
end
function disableLisn(obj,src,evnt)
obj.hLUpdateGraph.Enabled = false;
obj.hLLm.Enabled = false;
set(obj.hEnableCm,'Checked','off')
set(obj.hDisableCm,'Checked','on')
end
复制代码
在命令窗口中输入如下命令后,会出现如图8-3所示的执行效果。
>>funobj = MFunEval(@(x,y) 3*cos(x).*cos(y).*exp(-sqrt(x.^2+y.^2)/6),[-5 5]);
>>MAxes.CreateViews(funobj);
提示:第一条命令创建了一个MfunEval对象,构造函数中第一个参数是一个二元函数,用无名函数方式给出;第二个参数是区间,即函数计算区域是 。第二条命令是调用了坐标轴类MAxes中的静态方法CreateViews。
图8-3 利用事件模型更新图形
将鼠标移到在上面图形界面的左面坐标轴上点击右键,在弹出的上下文快捷菜单中选择“Don’t Listen”,在命令窗口再输入如下命令:
>>funobj.hFun=@(x,y) (x.^2+y.^2)
此对象funobj中的事件UpdateGraph被触发,由于左侧坐标轴对象听众的特性值Enabled为false,所有它不去执行回调函数listenUpdateGraph;而右侧听众的特性值Enabled为true,所有会去执行回调函数listenUpdateGraph。此时坐标轴上图形更新变化情况如图8-4所示。
图8-4 利用事件模型更新图形
同样输入:
>>funobj.Lm=[-10,10];
复制代码
会触发PostSet事件的发生,可改变函数绘图区间,并有相同的更新效果。
|
zan
|