Matlab 版 (精华区)
发信人: bage (最近比较烦), 信区: Matlab
标 题: 精通Matlab(十六
发信站: 哈工大紫丁香 (Sun Feb 4 14:04:28 2001), 转信
发信人: Security (淼水), 信区: MathTools
发信站: BBS 水木清华站 (Tue Jun 1 22:42:08 1999)
独立的回调函数
建立GUI函数的一个有效方法是编写独立的回调函数,专门执行一个或多个回调。函数使用的对象句柄和其它变量可以作为参量传递,必要时回调函数可返回值。
考虑先前的一个例子,建立一个方位角的滑标,以脚本文件来实现。
% setview.m script file
vw=get(gca, ' View ' );
Hc_az=uicontrol(gcf, ' Style ' , ' slider ' ,...
' Position ' ,[10 5 140 20],...
' Min ' ,-90, ' Max ' ,90, ' Value ' ,vw(1),...
' Callback ' ,[...
' set(Hc_cur, ' String ' ,num2str(get(Hc_az, ' Value ' ))), ' ...
' set(gca, ' View ' ,[get(Hc_az, ' Value ' ) vw(2)]) ' ]);
Hc_min=uicontrol(gcf, ' style ' , ' text ' ,...
' Position ' ,[10 25 40 20],...
' String ' ,num2str(get(Hc_az, ' Min ' )));
Hc_max=uicontrol(gcf, ' Style ' , ' text ' ,...
' Position ' ,[110 25 40 20],...
' String ' ,num2str(get(Hc_az, ' Max ' )));
Hc_cur=uicontrol(gcf, ' Style ' , ' text ' ,...
' Position ' ,[60 25 40 20],...
' String ' ,num2str(get(Hc_az, ' Value ' )));
下面是同样的例子。作为一个函数,采用 ' Tag ' 属性来辨别控制框,并使用独立的M文件来执行回调。
funtion setview( )
vw=get(gca, ' View ' );
Hc_az=uicontrol(gcf, ' Style ' , ' Slider ' ,...
' Position ' ,[10 5 140 20],...
' Min ' ,-90, ' Max ' ,90, ' Value ' ,vw(1),...
' Tag ' , ' Azslider ' ,...
' Callback ' , ' svcback ' );
Hc_min=uicontrol(gcf, ' style ' , ' text,...
' Position ' ,[10 25 40 20],...
' String ' ,num2str(get(Hc_az, ' Min ' )));
Hc_max=uicontrol(gcf, ' Style ' , ' text ' ,...
' Position ' ,[110 25 40 20],...
' String ' ,num2str(get(Hc_az, ' Max ' )));
Hc_cur=uicontrol(gcf, ' Style ' , ' text ' ,...
' Position ' ,[60 25 40 20],...
' Tag ' , ' Azcur ' ,...
' String ' ,num2str(get(Hc_az, ' Value ' )));
回调函数本身如下:
function svcback( )
vw = get(gca, ' View ' );
Hc_az = findobj(gcf, ' Tag ' , ' AZslider ' );
Hc_cur = findobj(gcf, ' Tag ' , ' AZcur ' );
str = num2str(get(Hc_az, ' Value ' ));
newview =[get(Hc_az, ' Value ' ) vw(2)];
set(Hc_cur, ' String ' ,str)
set(gca, ' View ' ,newview)
上面的例子并不节省很多代码,但却得到了用函数而不用脚本文件的优点:回调函数可以利用临时变量,而不使命令窗口工作空间拥挤;不需要eval所需的引号和字符串;在回调函数中命令的句法变得十分简单。使用独立回调函数技术,越复杂的回调(函数)越简单。
独立回调函数的缺点是:需要很大数目的M文件以实现一个含有若干控制框和菜单项的GUI函数,所有这些M文件必须在MATLAB路径中可得,且每一个文件又必须要有一个不同的文件名。在对文件名大小有限制且对大小写不敏感的平台上,如MS-windows,文件冲突的机会就增加了。而且回调
函数只能被GUI函数调用而不能被用户调用。
递归函数调用
利用单独的M文件并递归地调用该文件,既可以避免多个M文件的复杂性,又可以利用函数的优点。使用开关 switches或if elseif语句,可将回调函数装入调用函数内。通常这样一种函数调用的结构为
function guifunc(switch)。
其中switch确定执行哪一个函数开关的参量,它可以是字符串 ' startup ' , ' close ' , ' sectolor ' 等等,也可以是代码或数字。如switch是字符串,则可如下面所示的M文件片段那样将开关编程。
if nargin < 1, switch = ' startup ' ; end;
if ~isstr(switch), error( ' Invalid argument ' ), end;
if strcmp(switch, ' startup ' ),
<statement to create controls or menus>
<statements to implement the GUI function>
elseif strcmp(switch, ' setcolor ' ),
<statements to perform the Callback associated with setcolor>
elseif strcmp(switch, ' close ' ),
<statements to perform the Callback associated with close>
end
如果是代码或字符串,开关也可以相同方式编程。
if nargin < 1, switch = 0; end;
if isstr(switch), error( ' Invalid argument ' ), end;
if switch = = 0,
<statements to create controls or menus>
<statements to implement the GUI function>
elseif switch = =1,
<statements to perform the Callback associated with setcolor>
elseif switch ==2,
<statements to perform the Callback associated with close>
end
下面的例子说明了方位角滑标如何可作为单独的函数M文件来实现:
function setview(switch)
if nargin < 1, switch = ' startup ' ; end;
if ~isstr(switch), error( ' Invalid argument. ' ); end;
vw = get(gca, ' view ' ); % This information is needed in both sections
if strcmp(switch, ' startup ' ) % Define the controls and tag them
Hc_az = uicontrol(gcf, ' Style ' , ' slider ' ,...
' Position ' ,[10 5 140 20],...
' Min ' ,-90, ' Max ' ,90, ' Value ' vw(1),...
' Tag ' , ' AZslider ' ,...
' Callback ' , ' setview( ' set ' ) ' );
Hc_min=uicontrol(gcf, ' Style ' , ' text ' ,...
' Position ' ,[10 25 40 20],...
' String ' ,num2str(get(Hc_az, ' Min ' )));
Hc_max = uicontrol(gcf, ' Style ' , ' text ' ,...
' Position ' ,[110 25 40 20],...
' String ' ,num2str(get(Hc_az, ' Max ' )));
Hc_cur =uicontrol(gcf, ' Style ' , ' text ' ,...
' Position ' ,[60 25 40 20],...
' Tag ' , ' AZcur ' ,...
' string ' ,num2str(get(Hc_az, ' Value ' )));
elseif strcmp(switch, ' set ' ) % Execute the Callback
Hc_az=findobj(gcf, ' Tag ' , ' AZslider ' );
Hc_cur-findobj(gcf, ' Tag ' , ' AZcur ' );
str = num2str(get(Hc_az, ' Value ' ));
newview - [get(Hc_az, ' Value ' ) vw(2)];
set(Hc_cur, ' String ' , str)
set(gca, ' View ' ,newview)
end
上述的两个例子均设置了 ' tag ' 属性,利用该属性和函数findobj寻找回调函数所需对象的句柄。另外两种方法将在下章描述。
全局变量
全局变量可用在函数中,使某些变量对GUI函数的所有部分都可用,全局变量是在函数的公共区说明,因此整个函数以及所有对函数的递归调用都可以利用全局变量,下面的例子说明如何利用全局变量将方位角滑标编程。
function setview(switch)
global HC_AZ HC_CUR % Create global variables
if nargin < 1, switch = ' startup ' ; end;
if ~isstr(switch, error( ' Invalid argument. ' ); end;
vw = get (gca, ' View ' ); % This information is needed in both sections
if strcmp(switch, ' startup ' ) % Define the controls
Hc_AZ=uicontrol(gcf, ' style ' , ' slider ' ,...
' Position ' ,[10 5 140 20],...
' Min ' ,-90, ' Max ' ,90, ' Value ' ,vw(1),...
' Callback ' , ' setview( ' set ' ) ' );
Hc_min=uicontrol(gcf, ' Style ' , ' text ' ,...
' Position ' ,[10 25 40 20],...
' String ' ,num2str(get(Hc-AZ, ' Min ' ,)));
HcMax=uicontrol(gcf, ' Style ' , ' text ' ,...
' Position ' ,[110 25 40 20],...
' String ' ,num2str(get(Hc_AZ, ' Max ' )));
Hc_cur=uicontrol(gcf, ' style ' , ' text ' ,...
' Position ' ,[60 25 40 20],...
' String ' ,num2str(get(HC_AZ, ' Value ' )));
elseif strcmp(switch, ' set ' ) % Execute the Callback
str=num2str(get(HC_AZ, ' Value ' ));
newview= [get(HC_AZ, ' Value ' ) vw(2)];
set(HC_CUR, ' String ' ,str)
set(gca, ' View ' ,newview)
end
全局变量遵循MATLAB的规定,变量名要大写。不需要 ' tag ' 属性,且不使用它,另外因为对象句柄存在的,不需要用函数findobj去获取,故回调代码比较简单,全局变量通常使一个函数更有效。
不过有一点要注意,尽管一个变量在函数内说明为全局的,变量并不能自动地在命令窗口工作空间中利用,也不能在回调字符串内使用。但是,如果用户发命令:>> clear global,则所有全局变量则都被破坏,包括在函数内定义的那些变量。
当单独的一个图形或有限个变量要被所有的回调(函数)利用时,全局变量使用和递归性函数调用都是有效的技术。对于包含多个图形的更复杂的函数,或用独立对象回调函数实现的情况, ' UserData ' 属性更合适。另外,只要可获得对象句柄,对象 ' UserData '
的属性值在命令窗口工作空间中是存在的。
用户数据属性
同属性 ' Tag ' 一样, ' UserData ' 属性可在函数之间或递归函数的不同部分之间传递信息。如果需要多个变量,这些变量可以在一个容易辨识的对象的属性 ' UsetData ' 中传递。如前面所述, 对与句柄图形对象在一起的单个数据矩阵' UserData '
提供了存储。下面的程序利用了当前图形的 ' UserData ' 属性来实现方位角滑标。
function setview(switch)
if nargin < 1, switch = ' startup ' ; end;
vw = get(gca, ' View ' ); % This information is needed in both sections
if strcmp(switch, ' startup ' ) % Define the controls
Hc_az = uicontrol(gcf, ' Style ' , ' slider ' ,...
' Position ' ,[10 5 140 20],...
' Min ' ,-90, ' Max ' ,90, ' Value ' ,vw(1),...
' Callb的特殊形式的drawnow。
Drawnow
Drawnow命令迫使MATLAB更新屏幕,只要MATLAB回到命令提示,或执行drawnow,figure,getframe或pause命令,屏幕就更新。drawnow的特殊形式draunow( ' discard ' )使事件队列中所有事件的放弃。在回调中将drawnow( ' discard '
)包含在一个特殊命令之前,就含有清除事件队列的效果,防止刷新事件,以及回调事件中断回调。
21.8 M文件举例
精通MATLAB工具箱中一些函数阐明了上面所讨论的若干技术。第一个例子mmview3d应用全局变量和递归函数调用,把方位角和仰角滑标加到图形中。函数中有大量的对象,但函数很直观。因为mmview3d文件相当得长,故分段表示。第一段定义了函数标号,帮助文本和全局变量。
function mmview3d(cmd)
% MMVIE3D GUI controllled Azimuth and Elevation adustment.
% for adjusting azimuth and elevation using the mouse.
%
% The ' Revert ' pushbutton reverts to the original view.
% The ' cmd ' argument executes the callbacks.
% Copyright (c) 1996 by Prentice-Hall, Inc.
global Hc_acur Hc_esli Hc_ecur CVIEW
第二段处理初始用户的调用,建立必要的uicontrol对象并把回调定义为递归函数调用。
if nargin==0
%------------------------------------------------------------------
% Assign a handle to the current figure window.
% Get the current view for slider initial values.
% Use normalized uicontrol units rather than the default ' pixels ' .
%------------------------------------------------------------------
Hf_fig=gcf;
CVIEW=get(gca, ' View ' );
if abs(CVIEW(1))>180, CVIEW(1)=CVIEW(1)-(360*sign(CVIEW(1)));end
set(Hf_fig, ' DefaultUicontrolUnits ' , ' normalized ' );
%-------------------------------------------------------------------
% Define azimuth and elevation sliders.
% The position is in normalized units (0-1).
% Maximum, minimum, and initial values are set.
%--------------------------------------------------------------------
Hc_asli=uicontrol(Hf_fig, ' style ' , ' slider ' ,...
' position ' ,[.09 .02 .3 .05],...
' min ' ,-180, ' max ' ,180, ' value ' , CVIEW(1),...
' callback ' , ' mmview3d(991) ' );
Hc_esli=uicontrol(Hf_fig, ' style ' , ' slider ' ,...
' position;,[.92 .5 .04 .42],...
' min ' ,-90, ' max ' ,90, ' val ' ,CVIEW(2),...
' callback ' , ' mmview3d(992) ' );
%--------------------------------------------------------------------
% Place the text boxes showing the minimum and maximum values at the
% ends of each slider, These are text displays, and cannot be edited.
%---------------------------------------------------------------------
uicontrol(Hf_fig, ' style ' , ' text ' ,...
' pos ' ,[.02 .02 .07 .05],...
' string ' ,num2str(get(Hc_asli, ' min ' )));
uicontrol(Hf_fig, ' style ' , ' text ' ,...
' pos ' ,[.39 .02 .07 .05],...
' string ' ,num2str(get(Hc_esli, ' min ' )));
uicontrol(Hf_fig, ' style ' , ' text ' ,...
' pos ' ,[.915 .92 .05 .05],...
' string ' ,num2str(get(Hc_esli, ' max ' )));
%--------------------------------------------------------------------
% Place labels for each slider
%--------------------------------------------------------------------
uicontrol(Hf_fig, ' style ' , ' text ' ,...
' pos ' ,[9.095 .08 .15 .05],...
' string ' , ' Azimuth ' );
uicontrol(Hf_fig, ' style ' , ' text ' ,...
' pos ' ,[.885 .39 .11 .05],...
' string ' , ' Elevation ' );
%-------------------------------------------------sition
MMCXY_OUT=cp(1,1:2);
xystr=sprintf( ' [%.3g] ' ,MMCXY_OUT);
Hu=get(gcf, ' Userdata ' );
set(Hu, ' String ' xystr) % put x-y coordinaates in text box
elseif strcmp(arg, ' end ' ) % mouse click occurred, clean things up
Hu=get(gcf, ' Userdata ' );
set(Hu, ' visible ' , ' off ' ) % make sure text box disappears
delete(Hu)
set(gcf, ' Pointer ' , ' arrow ' ,...
' WindowButtonMotionFcn ' , ' ' ,...
' WindowButtonDownFcn ' , ' ' ,...
' Userdata ' ,[])
end
第一次被调用时,mmcxy建立文本uicontrol,改变指针形状,设定 ' WindowButtonDownFcn ' 和 ' WindowButtonMotionFcn ' 的回调,然后等待按键或先揿按钮。若有键揿下,就调用清除(cleanup)程序,清除文本框,恢复鼠标指针,清除图形回调及 ' UserData '
属性。若点击鼠标按钮, ' WindowButtonDownFcn ' 回调就处理清除任务。在等待时,图形中鼠标指针的移动会触发 ' WindowButtonMotionFcn ' 回调,更新uicontrol中文本串。
精通MATLAB工具箱中的另一个函数是mmtext,它利用 ' WindowButtonDownFcn ' , ' WindowButtonUpFcn ' 和 ' WindowButtonMotionFcn ' 回调的另一个短小函数以安置和拖曳文本。
function mmtext(arg)
% MMTEXT place and drag text with mouse
% MMTEXT waits for a mouse click on a text object
% in the current figure then allows it to be dragged
% while the mouse button remains down.
% MMTEXT( ' whatever ' ) places the string ' whatever ' on
% the current axes and allows it to be dragged.
%
% MMTEXT becomes inactive after the move is complete or
% no text object is selected.
% Copyright (c) 1996 by Prentice-Hall, Inc.
if -nargin, arg=0;end
if isstr(arg) % user entered text to be placed
Ht=text( ' units ' , ' normalized ' ,...
' Position ' ,[.05 .05],...
' String ' ,arg,...
' HorizontalAlignment ' , ' left ' ,...
' VerticalAlignment ' , ' baseline ' );
mmtext(0) % call mmtext again to drag it
elseif arg==0 % initial call, select text for dragging
Hf=mmgcf;
if isempty(Hf), error( ' No Figure Available. ' ), end
set(Hf, ' BackingStore ' , ' off ' ,...
' WindowButtonDownFcn ' , ' mmtext(1) ' )
figure(Hf) % bring figure forward
elseif arg==1 & strcmp(get(gco, ' Type ' ), ' text ' ) % text object selected
--
--
☆ 来源:.哈工大紫丁香 bbs.hit.edu.cn.[FROM: bage.bbs@smth.org]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:209.118毫秒