数学建模社区-数学中国

标题: 一个例子 [打印本页]

作者: 建不了的模。    时间: 2014-12-30 10:37
标题: 一个例子
前面介绍了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事件的发生,可改变函数绘图区间,并有相同的更新效果。



作者: 光之仑    时间: 2014-12-30 17:04
好                             

作者: w785485068    时间: 2015-1-2 15:18
顶一下。。。。。





欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5