《量化投资:以MATLAB为工具》

MATLAB技术论坛

 找回密码
 注册账号
查看: 2048|回复: 0
收起左侧

[样章] 8.2.6 一个例子

[复制链接]
发表于 2014-7-10 11:22:18 | 显示全部楼层 |阅读模式
23344fm.jpg

前面介绍了MATLAB中事件模型的基本原理和设计方法。下面通过一个完整的实例来实现事件模型的具体设计过程。

例8-2  建立一个图形用户界面,要求:
(1)在界面上用subplot命令绘制两个坐标轴,在每个坐标轴上各绘制一个曲面;
(2)利用函数的变化和函数区间的变化来触发件,通过事件来及时更新函数图形的绘制;
(3)通过上下文菜单来设置各个坐标轴是否收听事件。
分析:在本例中涉及到两个事件来对应函数变化情况和自变量区间变化情况。函数的变化情况可以在events块中定义一个普通的事件UpdateGraphics来描述,而函数区间的变化情况可以采用PostSet事件来设置。这样,就需要定义两个听众来响应这两个事件。利用听众的Enabled特性来设置是否收听这些事件。
解:为解决本例问题,需要设计两个类,一个是函数运算类MfunEval,在这个类中定义一个函数句柄hFun和区间变量Lm,并在其中events块中定义一个UpdateGraph事件,另一个是坐标轴类Maxes,在其中定义两个听众对象,并与相应的回调函数相关联实现绘图更新。
本实例文件目录结构如图8-2所示。
文件MFunEval.m中的代码为:
  1. classdef  MFunEval< handle  %函数计算类
  2.     properties
  3.       hFun              %函数句柄
  4.     end
  5.     properties (SetObservable = true)
  6.        Lm = [];   %区间
  7.     end
  8.     properties (Dependent = true)
  9.        Data     %保存网格化数据
  10.     end  
  11.     events
  12.        UpdateGraph   %更新图形
  13.     end
  14.     methods
  15.       function obj = MFunEval(fcn_handle,limits)         %构造函数
  16.        obj.hFun = fcn_handle;
  17.        obj.Lm = limits;
  18.       end
  19.       function fofxy = set.hFun(obj,func)
  20.         obj.hFun = func;
  21.         notify(obj,'UpdateGraph');                                   %广播事件
  22.       end
  23.       function data = get.Data(obj)                                    %获取网格化数据
  24.        [x,y] = MFunEval.grid(obj.Lm);
  25.        matrix = obj.hFun(x,y);
  26.        data.X = x;
  27.        data.Y = y;
  28.        data.Matrix = matrix;
  29.       end
  30.     end
  31.     methods (Static)
  32.         function [x,y] = grid(lim)                                   %网格化
  33.           inc = (lim(2)-lim(1))/20;
  34.           [x,y] = meshgrid(lim(1):inc:lim(2));
  35.         end
  36.     end   
  37. end
复制代码
文件MAxes.m中的代码为:
  1. classdef MAxes < handle           %坐标轴类
  2.    properties
  3.       FunObject  = []                    %函数计算类对象
  4.       hLUpdateGraph = []              %图形更新听众句柄
  5.       hLLm = []                       %区间Lm的PostSet事件听众句柄
  6.       hEnableCm = []                  %上下文菜单“Listen”句柄
  7.       hDisableCm = []                 %上下文菜单“Don't Listen”句柄
  8.       hAxes = [];                      %坐标轴句柄
  9.       hSurface = []                     %曲面对象句柄
  10.    end  
  11.    methods
  12.       function obj= MAxes(funobj)  
  13.         obj.FunObject = funobj;
  14.         obj.CreateLisn;  %创建听众   
  15.       end
  16.       function CreateLisn(obj)  %创建两个听众
  17.           obj.hLUpdateGraph = addlistener(obj.FunObject,'UpdateGraph',...
  18.                            @(src,evnt)listenUpdateGraph(obj,src,evnt));
  19.           obj.hLLm = addlistener(obj.FunObject,'Lm','PostSet',...
  20.                          @(src,evnt)listenLm(obj,src,evnt));
  21.       end
  22.       %听众1的回调函数
  23.       function listenUpdateGraph(obj,src,evnt)  %更新图形
  24.           if ishandle(obj.hSurface)
  25.               obj.updateSurfaceData
  26.           end
  27.       end
  28.       function updateSurfaceData(obj)
  29.            data = obj.FunObject.Data;
  30.            set(obj.hSurface,...
  31.                'XData',data.X,...
  32.                'YData',data.Y,...
  33.                'ZData',data.Matrix);
  34.       end
  35.       %听众2的回调函数
  36.       function listenLm(obj,src,evnt)
  37.              if ishandle(obj.hAxes)
  38.                  lims(obj);
  39.                  if ishandle(obj.hSurface)
  40.                      obj.updateSurfaceData
  41.                  end
  42.              end
  43.       end
  44.       function lims(obj)
  45.            lmts = obj.FunObject.Lm;
  46.            set(obj.hAxes,'XLim',lmts);
  47.            set(obj.hAxes,'Ylim',lmts);
  48.       end
  49.       function delete(obj)  %析构函数
  50.           if ishandle(obj.hAxes)
  51.               delete(obj.hAxes);
  52.           else
  53.               return
  54.           end
  55.       end
  56. end
  57.     methods (Static = true)
  58.         function CreateViews(funobj)  %绘制曲面
  59.              hFigure = figure('Name','利用事件模型更新图', 'Toolbar','none');
  60.             for k=1:2
  61.               axesobj(k)= MAxes(funobj);  %定义坐标轴对象
  62.               axh=subplot(1,2,k);
  63.               axesobj(k).hAxes=axh;
  64.               hcm(k)=uicontextmenu;  %上下文菜单
  65.               set(axesobj(k).hAxes,'Parent',hFigure,...
  66.                  'FontSize',8,...
  67.                  'UIContextMenu',hcm(k));
  68.                axesobj(k).hEnableCm = uimenu(hcm(k),...
  69.                   'Label','Listen',...
  70.                    'Checked','on',...
  71.                   'Callback',...
  72.                   @(src,evnt)enableLisn(axesobj,src,evnt));
  73.                axesobj(k).hDisableCm = uimenu(hcm(k),...
  74.                   'Label','Don''t Listen',...
  75.                    'Checked','off',...
  76.                   'Callback',...
  77.                   @(src,evnt)disableLisn(axesobj(k),src,evnt));
  78.                 view(axesobj(k).hAxes,60,30)
  79.                 axesobj(k).lims;
  80.                 surfLight(axesobj(k),axesobj(k).hAxes);  %绘制曲面
  81.              end
  82.         end
  83.     end
  84. end
复制代码
以下是三个全局函数:
  1. function surfLight(obj,axh)
  2.            obj.hSurface = surface(obj.FunObject.Data.X,...
  3.            obj.FunObject.Data.Y,...
  4.            obj.FunObject.Data.Matrix,...
  5.            'FaceColor',[.8 .8 0],'EdgeColor',[.3 .3 .2],...
  6.            'FaceLighting','phong',...
  7.            'FaceAlpha',.3,...
  8.            'HitTest','off',...
  9.            'Parent',axh);
  10.            lims(obj)
  11.            camlight left; material shiny; grid off
  12.            colormap copper
  13. end
  14. function enableLisn(obj,src,evnt)
  15.             obj.hLUpdateGraph.Enabled = true;
  16.             obj.hLLm.Enabled = true;
  17.             set(obj.hEnableCm,'Checked','on')
  18.             set(obj.hDisableCm,'Checked','off')
  19.         end
  20. function disableLisn(obj,src,evnt)
  21.             obj.hLUpdateGraph.Enabled = false;
  22.             obj.hLLm.Enabled = false;
  23.             set(obj.hEnableCm,'Checked','off')
  24.             set(obj.hDisableCm,'Checked','on')
  25. 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  利用事件模型更新图形
同样输入:
  1. >>funobj.Lm=[-10,10];
复制代码
会触发PostSet事件的发生,可改变函数绘图区间,并有相同的更新效果。

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

QQ|网站地图|MATLAB技术论坛|Simulink仿真论坛 ( 蜀ICP备19014457号-2 

GMT+8, 2022-12-5 21:39 , Processed in 0.058040 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表