1、MATLAB GUI图形界面 独立回调函数独立的回调函数建立GUI函数的一个有效方法是编写独立的回调函数,专门执行一个或多个回调。函数使用的对象句柄和其它变量可以作为参量传递,必要时回调函数可返回值。考虑先前的一个例子,建立一个方位角的滑标,以脚本文件来实现。% setview.m script filevw=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
2、,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 ,
3、. 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=uicontro
4、l(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 );回调函数本身如下:fu
5、nction 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所需的引号和字
6、符串;在回调函数中命令的句法变得十分简单。使用独立回调函数技术,越复杂的回调(函数)越简单。独立回调函数的缺点是:需要很大数目的M文件以实现一个含有若干控制框和菜单项的GUI函数,所有这些M文件必须在MATLAB路径中可得,且每一个文件又必须要有一个不同的文件名。在对文件名大小有限制且对大小写不敏感的平台上,如MS-windows,文件冲突的机会就增加了。而且回调函数只能被GUI函数调用而不能被用户调用。递归函数调用利用单独的M文件并递归地调用该文件,既可以避免多个M文件的复杂性,又可以利用函数的优点。使用开关 switches或if elseif语句,可将回调函数装入调用函数内。通常这样一种
7、函数调用的结构为 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 ), elseif strcmp(switch, setcolor ), elseif strcmp(
8、switch, close ), end如果是代码或字符串,开关也可以相同方式编程。if nargin 1, switch = 0; end;if isstr(switch), error( Invalid argument ), end;if switch = = 0, elseif switch = =1, elseif switch =2, end下面的例子说明了方位角滑标如何可作为单独的函数M文件来实现:function setview(switch)if nargin 1, switch = startup ; end;if isstr(switch), error( Invalid
9、 argument. ); end;vw = get(gca, view ); % This information is needed in both sectionsif 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=
10、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 )
11、;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寻找回调函数所需对象的句柄。另外两种方法
12、将在下章描述。全局变量全局变量可用在函数中,使某些变量对GUI函数的所有部分都可用,全局变量是在函数的公共区说明,因此整个函数以及所有对函数的递归调用都可以利用全局变量,下面的例子说明如何利用全局变量将方位角滑标编程。function setview(switch)global HC_AZ HC_CUR % Create global variablesif nargin clear global,则所有全局变量则都被破坏,包括在函数内定义的那些变量。当单独的一个图形或有限个变量要被所有的回调(函数)利用时,全局变量使用和递归性函数调用都是有效的技术。对于包含多个图形的更复杂的函数,或用独立对
13、象回调函数实现的情况, UserData 属性更合适。另外,只要可获得对象句柄,对象 UserData 的属性值在命令窗口工作空间中是存在的。用户数据属性同属性 Tag 一样, UserData 属性可在函数之间或递归函数的不同部分之间传递信息。如果需要多个变量,这些变量可以在一个容易辨识的对象的属性 UsetData 中传递。如前面所述, 对与句柄图形对象在一起的单个数据矩阵 UserData 提供了存储。下面的程序利用了当前图形的 UserData 属性来实现方位角滑标。function setview(switch)if nargin 1, switch = startup ; end;
14、vw = get(gca, View ); % This information is needed in both sectionsif 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 4
15、0 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 ); set(gcf, UserData ,Hc_az Hc_cur); % Store the object handles
16、elseif strcmp(switch, set ) % Execute the Callback Hc_all = get(gcf, UserData ); % retrieve the object handles Hc_az = Hc_all(1); Hc_cur = Hc_all(2); str = num2str(get(Hc_az, Value ); newview = get(Hc_az, Value ) vw(2); set(Hc_cur, String ,str) set(gca, View ,newview)end句柄存储于 startup 末端,图形 属性 UserDa
17、ta 中,在回调被执行前对此进行检索。如果有许多回调,如下面的程序片断所示, UserData 只需检索一次。if strcmp(switch, startup ) % Define the controls and tag them % set(gcf, UserData ,Hc_az Hc_cur); % Store the object handleselse % This must be a Callback Hc_all=get(gcf, UserData ); % Retrieve the object handles Hc_az=Hc_all(1); Hc_cur=Hc_all(
18、2); if strcmp(switch, set ) % elseif strcmp (switch, close ) % % endend调试GUI M文件回调字符串在命令窗口工作空间中计算并执行的,这个情况对编写和调试GUI函数和脚本文件有某种隐含意义。回调字符串可以很复杂,尤其是在脚本文件中,这为句法错提供了许多机会,记录单引号、逗号、括号是令人头痛的事。如果出现了句法错误,MATLAB给出提示;只要对象的 Callback 属性值是一个真正的文本串,MATLAB就认可了。只有当对象被激活并将回调字符串传给eval时,才检查回调字符串内部的句法错误。这样让用户定义回调字符串,它涉及还未
19、曾定义过的对象句柄和变量,这使编写相互参照的程序变得更容易,但是每个回调函数必须分别测试,保证回调字符串是合法的MATLAB命令,并且回调字符中涉及的所有变量可在命令窗口工作空间中是可利用的。将回调象函数M文件一样编程或象GUI函数本身内的开关一样编程,就可以不运行整个GUI函数而对各个回调进行改变或测试。因为回调字符串是在命令窗工作空间中而不在函数本身内计算,在函数与各回调之间传递数据就变得十分复杂。例如,函数test包含如下程序:function test()tpos1=20 20 50 20;tpos2=20 80 50 20;Hc_text=uicontrol( Style , tex
20、t , String , Hello , Position ,tposl);Hc-push=uicontrol( Style , push , String , Move Text ,. Position ,15 50 100 25,. Callback , set(Hc-text,Position,tpos2) );所有语句都是有效的MATLAB命令,且回调字符串也对有效的MATLAB语句估值。文本对象和按钮出现在图形上,但当激活按钮键时,MATLAB就出示错误。 test? Undefined functiion or variable Hc_text.? Error while eval
21、uating Callback string.如果test是个脚本文件,就不会出现这样问题,因为所有变量可在命令窗口工作空间中使用,因为test是个函数,Hc_text和tpos2在命令窗口工作空间中均未定义,回调字符串执行失败。一种解决方法是使用各个字符串元素来建立回调,该字符串元素由数值而非变量建立,例如,改变回调字符串如下: Callback , set9 ,. sprintf( &.15g ,Hc_text),. , Position , ,. sprintf( %.15g %.15g %.15g %.15g ,tpos2),. ) );建立了包括Hc_text对象句柄值的一个字符串,
22、该值变换成具有15位精度的字符串,而tpos2变量转换成矩阵表示的字符串。在函数内计算sprinf语句,然后将所得的字符串用在回调中。在命令窗工作空间执行的实际命令如下所示 eval( set(87.000244140625, Position ,20 80 50 100) )将一个对象句柄转换为字符串,必须保持全精度。上例中的变换,使用了小数点后15位的数字的精度。在MATLAB中句柄对象转换应使用这样的精度。要记住,变量随后的变换不会改变回调字符串。在前面的例子中,在控制框定义之后改变tpos2的值,就无效果。例如,在函数结尾处加命令 tpos2=20 200 50 20 就无效果,因为在
23、tpos2重新定义之前,通过计算tpos2,回调字符串已经建立。21.6 指针和鼠标按钮事件GUI函数利用鼠标箭头的位置和鼠标按钮的状态来控制MATLAB行动。本节讨论指针、对象位置和鼠标按钮动作之间的交互,以及MATLAB如何响应变化或事件,诸如:揿下按钮、松开按钮或箭头移动等。回调属性,选择区域和堆积顺序所有句柄图形对象具有一个至今还未阐述过的 ButtonDownFcn 属性,本节就进行讨论。uimenu和uicontrol均有 CallBack 属性,这个属性是菜单和控制框的应用核心。另外,图形有 KeyPressFcn 和 ResizeFcn 属性以及 WindowButtonUpFc
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2