独立的回调函数 建立GU函数的一个有效方法是编写独立的回调函数,专门执行一个或多个回调。函数使 用的对象句柄和其它变量可以作为参量传递,必要时回调函数可返回值。 考虑先前的一个例子,建立一个方位角的滑标,以脚本文件来实现 setview. m script file vw=get(gca, 'View); Hc azuicontrol(gcf,' Style,slider Position',[10514020] Min",-90,'Max',90," Value',w(1), Callback’,[ set(Hc cur,'String, num2str(get(Hc az,'Value)) set(gca, 'View, [get(Hc az,'Value ')vw(2)D D): He min=uncontrol(gcf, 'style,'text Position',[10254020], String, num2str(get(Hc az, Min)): He max=uncontrol(gcf,' Style,text Position',[110254020 He cur=uncontrol(gcf,'Style,text Position',[60254020], i Value 下面是同样的例子。作为一个函数,采用’Tag’属性来辨别控制框,并使用独立的M文件来执 行回调 vw=get(gca, 'View): He azuicontrol(gcf,'Style,'Slider Position'",[10514020 Min',-90,.Max, 90, valu w(1), ) He min=uncontrol(gcf, 'style,'text String, num2str( get(Hc az,Min): He max=uncontrol(gcf, Style,text Position',[110254020]
独立的回调函数 建立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 ' )));
He cur=uncontrol(gcf, ' Style,text Position',[60254020, Tag",’ Azur String, num2str(get(Hc az,'Value D)) 调函数本身如下 function svcbacko ww=get(gca,'View) He az=findobj(gcf, 'Tag,'AZslider): He cur= findobj(gcf, 'Tag,' AZcur') str =num2str(get( Hc az, 'Value)): eview=get(Hc az, 'Value ')vw(2)] set(He cur,'String,str t(gca,View, newview) 上面的例子并不节省很多代码,但却得到了用函数而不用脚本文件的优点:回调函数可以利用 临时变量,而不使命令窗口工作空间拥挤;不需要eva所需的引号和字符串;在回调函数中命 令的句法变得十分简单。使用独立回调函数技术,越复杂的回调(函数)越简单 独立回调函数的缺点是:需要很大数目的M文件以实现一个含有若干控制框和菜单项的 GU函数,所有这些M文件必须在 MATLAB路径中可得,且每一个文件又必须要有一个不同的 文件名。在对文件名大小有限制且对大小写不敏感的平台上,如Ms- windows,文件冲突的机 会就增加了。而且回调函数只能被GUI函数调用而不能被用户调用 递归函数调用 利用单独的M文件并递归地调用该文件,既可以避免多个M文件的复杂性,又可以利用函 数的优点。使用开关 switches或 if elseif语句,可将回调函数装入调用函数内。通常这样一种函 数调用的结构为 function guifunc(switch) 其中 switch确定执行哪一个函数开关的参量,它可以是字符串' startup','cose',' sectolor 等等,也可以是代码或数字。如 switch是字符串,则可如下面所示的M文件片段那样将开关编 程 if nargin elseif strcmp(switch, 'setcolor)
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 elseif strcmp(switch, ' setcolor ' ), elseif strcmp(switch, ' close ' )
如果是代码或字符串,开关也可以相同方式编程。 if nargin elseif switch==l, elseif switch =2 statements to perform the Callback associated with close> 下面的例子说明了方位角滑标如何可作为单独的函数M文件来实现: function setview(switch ifr startup if -isstr(switch), error(Invalid argument. ): end vw=get(gca, 'view): This information is needed in both sections if strcmp(switch, '')% Define the controls and tag them He az= uncontrol(gcf, 'Style','slider, Position’,[10514020], Min',-90,'Max,90, 'Value'vw(1), i Tag',' AZslider Callback,'setview('set)); He min=uncontrol(gcf, Style,text Position'",[10254020] String, num2str(get(Hc az, 'Min )) He max=uncontrol(gcf,' Style,text Position',[0254020], String, num2str(get( Hc az,' Max )) He cur =uncontrol(gcf, 'Style,text Position',[60254020] Tag',' AZcur string, num2str(get(Hc az, 'Value ' )) elseif strcmp(switch,'set)% Execute the Callback He azfindobj(gcf, Tag,' AZslider'): He cur-findobj(gcf, 'Tag,'AZcur')
end 如果是代码或字符串,开关也可以相同方式编程。 if nargin elseif switch = =1, elseif switch ==2, 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-Iget( Hc az, ' Value')vw(2)] set(Hc cur,'String set(gca,'View, newview) 上述的两个例子均设置了’tag'属性,利用该属性和函数 findobj寻找回调函数所需对象的句 柄。另外两种方法将在下章描述 全局变量 全局变量可用在函数中,使某些变量对GUI函数的所有部分都可用,全局变量是在函数的 公共区说明,因此整个函数以及所有对函数的递归调用都可以利用全局变量,下面的例子说明 如何利用全局变量将方位角滑标编程 function seaview(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, '')% Define the controls Hc az=uncontrol(gcf, 'style,'slider Position',[10514020 Min',-90,'Max",90," Value',w(1) Callback,'setview( 'set)): He min=uncontrol(gcf, 'Style,text String, num2str(get(Hc-AZ, 'Min',)) HcMax-uicontrol(gcf, 'Style','text, Position',[10254020], String, num2str(get(Hc AZ,'Max)): He cur=uncontrol(gcf, 'style,text Position',[60254020, 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)
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)
全局变量遵循 MATLAB的规定,变量名要大写。不需要’tag'属性,且不使用它,另外因为对 象句柄存在的,不需要用函数 findobj去获取,故回调代码比较简单,全局变量通常使一个函数 更有效。 不过有一点要注意,尽管一个变量在函数内说明为全局的,变量并不能自动地在命令窗口 工作空间中利用,也不能在回调字符串内使用。但是,如果用户发命令:> clear global,则 所有全局变量则都被破坏,包括在函数内定义的那些变量。 当单独的一个图形或有限个变量要被所有的回调函数)利用时,全局变量使用和递归性函 数调用都是有效的技术。对于包含多个图形的更复杂的函数,或用独立对象回调函数实现的情 况,' UserData'属性更合适。另外,只要可获得对象句柄,对象' UserData'的属性值在命令 窗口工作空间中是存在的。 用户数据属性 同属性’Iag,一样, UserData’属性可在函数之间或递归函数的不同部分之间传递信 息。如果需要多个变量,这些变量可以在一个容易辨识的对象的属性' UserData’中传递。如 前面所述,对与句柄图形对象在一起的单个数据矩阵' User Data'提供了存储。下面的程序 利用了当前图形的' UserData'属性来实现方位角滑标。 function setview(switch 1, switch='startup: end: vw=get(gca, 'View): %This information is needed in both sections if strcmp(switch, 'startup')% Define the controls He az=uncontrol(gcf, 'Style,'slider Position',[10514020] Min,-90,'Max, 90,'Value, vw(1) Callback,' setview("set")): He min= uncontrol(gcf, 'Style,'text, Position’,[10254020], String,num2str(get(Hc az,' Min')); He max=uncontrol(gcf,' Style,text Position',[0254020] String, num2str(get( Hc az,' Max)): He cur=uncontrol(gcf,' Style,text Position',[60254020], String, num2str(get( Hc az,'Value)) set(gcf,'User Data,[Hc az Hc cur): % Store the object handles
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),... ' 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],... ' String ' ,num2str(get(Hc_az, ' Value ' ))); set(gcf, ' UserData ' ,[Hc_az Hc_cur]); % Store the object handles
elseif strcmp(switch, 'set)% Execute the Callback He all -get(gcf, 'User Data): %retrieve the object handles He 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) 句柄存储于' startup’末端,图形属性' UserData’中,在回调被执行前对此进行检索。 如果有许多回调,如下面的程序片断所示,' UserData'只需检索一次。 if strcmp(switch, 'startup)% Define the controls and tag them % set(gcf,'User Data,(Hc az Hc cur)): Store the object handles else This must be a Callback He all=get(gcf,'User Data); Retrieve the object handles Hc azHe all(1): He cur=Hc all (2): % Seif strcmp(switch,'close ') %o % 调试GUM文件 回调字符串在命令窗口工作空间中计算并执行的,这个情况对编写和调试GUI函数和脚本 文件有某种隐含意义。回调字符串可以很复杂,尤其是在脚本文件中,这为句法错提供了许多 机会,记录单引号、逗号、括号是令人头痛的事。如果出现了句法错误, MATLAB给出提 示;只要对象的· Callback’属性值是一个真正的文本串, MATLAB就认可了。只有当对象被 激活并将回调字符串传给eval时,才检查回调字符串内部的句法错误 这样让用户定义回调字符串,它涉及还未曾定义过的对象句柄和变量,这使编写相互参照 的程序变得更容易,但是每个回调函数必须分别测试,保证回调字符串是合法的 MATLA B命 令,并且回调字符中涉及的所有变量可在命令窗口工作空间中是可利用的 将回调象函数M文件一样编程或象GU函数本身内的开关一样编程,就可以不运行整个 GU函数而对各个回调进行改变或测试
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 ' 末端,图形 属性' UserData ' 中,在回调被执行前对此进行检索。 如果有许多回调,如下面的程序片断所示, ' UserData ' 只需检索一次。 if strcmp(switch, ' startup ' ) % Define the controls and tag them % set(gcf, ' UserData ' ,[Hc_az Hc_cur]); % Store the object handles else % This must be a Callback Hc_all=get(gcf, ' UserData ' ); % Retrieve the object handles Hc_az=Hc_all(1); Hc_cur=Hc_all(2); if strcmp(switch, ' set ' ) % elseif strcmp (switch, ' close ' ) % % end end 调试GUI M文件 回调字符串在命令窗口工作空间中计算并执行的,这个情况对编写和调试GUI函数和脚本 文件有某种隐含意义。回调字符串可以很复杂,尤其是在脚本文件中,这为句法错提供了许多 机会,记录单引号、逗号、括号是令人头痛的事。如果出现了句法错误,MATLAB给出提 示;只要对象的 ' Callback ' 属性值是一个真正的文本串,MATLAB就认可了。只有当对象被 激活并将回调字符串传给eval时,才检查回调字符串内部的句法错误。 这样让用户定义回调字符串,它涉及还未曾定义过的对象句柄和变量,这使编写相互参照 的程序变得更容易,但是每个回调函数必须分别测试,保证回调字符串是合法的MATLAB命 令,并且回调字符中涉及的所有变量可在命令窗口工作空间中是可利用的。 将回调象函数M文件一样编程或象GUI函数本身内的开关一样编程,就可以不运行整个 GUI函数而对各个回调进行改变或测试
因为回调字符串是在命令窗工作空间中而不在函数本身内计算,在函数与各回调之间传递 数据就变得十分复杂。例如,函数tst包含如下程序: function testO post=[20205020] tpos2=20805020 He text-uicontrol( Style,'text,'String,'Hello,'Position,tposl) Hc-push=uncontrol('Style,' push,'String, Move Text Position',[155010025], Callback,'set(Hc-text, Position,tpos2)): 所有语句都是有效的 MATLAB命令,且回调字符串也对有效的 MATLAB语句估值。文本 对象和按钮出现在图形上,但当激活按钮键时,MA∏LAB就出示错误。 > test 99? Undefined functiion or variable hc text ??? Error while evaluating Callback string 如果test是个脚本文件,就不会出现这样问题,因为所有变量可在命令窗口工作空间中使 用,因为test是个函数, He text和tpos2在命令窗口工作空间中均未定义,回调字符串执行失 种解决方法是使用各个字符串元素来建立回调,该字符串元素由数值而非变量建立,例 如,改变回调字符串如下: Callback,['set9, sprintf(& 15g, Hc text ' Position'',’, sprintf('%.15g %.15g %.15g %.15g,, tpos2) )"]) 建立了包括Hc_text对象句柄值的一个字符串,该值变换成具有15位精度的字符串,而tpos2变 量转换成矩阵表示的字符串。在函数内计算 sprin语句,然后将所得的字符串用在回调中。在 命令窗工作空间执行的实际命令如下所示 eval('set(87.000244140625, Position'',[208050100j)') 将一个对象句柄转换为字符串,必须保持全精度。上例中的变换,使用了小数点后15位的 数字的精度。在 MATLAB中句柄对象转换应使用这样的精度 要记住,变量随后的变换不会改变回调字符串。在前面的例子中,在控制框定义之后改变 tpos2的值,就无效果。例如,在函数结尾处加命令 tpos2=[202005020]
因为回调字符串是在命令窗工作空间中而不在函数本身内计算,在函数与各回调之间传递 数据就变得十分复杂。例如,函数test包含如下程序: function test() tpos1=[20 20 50 20]; tpos2=[20 80 50 20]; Hc_text=uicontrol( ' Style ' , ' text ' , ' 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 evaluating Callback string. 如果test是个脚本文件,就不会出现这样问题,因为所有变量可在命令窗口工作空间中使 用,因为test是个函数,Hc_text和tpos2在命令窗口工作空间中均未定义,回调字符串执行失 败。 一种解决方法是使用各个字符串元素来建立回调,该字符串元素由数值而非变量建立,例 如,改变回调字符串如下: ' Callback ' ,[ ' set9 ' ,... sprintf( ' &.15g ' ,Hc_text),... ' , ' ' Position ' ' , ' ,... sprintf( ' [%.15g %.15g %.15g %.15g] ' ,tpos2),... ' ) ' ]); 建立了包括Hc_text对象句柄值的一个字符串,该值变换成具有15位精度的字符串,而tpos2变 量转换成矩阵表示的字符串。在函数内计算sprinf语句,然后将所得的字符串用在回调中。在 命令窗工作空间执行的实际命令如下所示 eval( ' set(87.000244140625, ' ' Position ' ' ,[20 80 50 100]) ' ) 将一个对象句柄转换为字符串,必须保持全精度。上例中的变换,使用了小数点后15位的 数字的精度。在MATLAB中句柄对象转换应使用这样的精度。 要记住,变量随后的变换不会改变回调字符串。在前面的例子中,在控制框定义之后改变 tpos2的值,就无效果。例如,在函数结尾处加命令 tpos2=[20 200 50 20 ]
就无效果,因为在tpos2重新定义之前,通过计算tpos2,回调字符串已经建立 21.6指针和鼠标按钮事件 GU函数利用鼠标箭头的位置和鼠标按钮的状态来控制 MATLAB行动。本节讨论指针、对 象位置和鼠标按钮动作之间的交互,以及 MATLAB如何响应变化或事件,诸如:揿下按钮、 松开按钮或箭头移动等 回调属性,选择区域和堆积顺序 所有句柄图形对象具有一个至今还未阐述过的’ Button Down Fcn’属性,本节就进行讨 论。 yimeng和 contro均有' CallBack’属性,这个属性是菜单和控制框的应用核心。另外 图形有’ KeyPressFcn和’ Resize fen'属性以及’ window ButtonUpFcn’和 Window Button Motion Fcn’属性。与这些属性相关的值是回调字符串,即 MATLAB字符串 当属性激活时,它传给eval。指针的位置确定事件涉及到哪些回调以及当事件发生时它们被激 励的顺序 章讨论过堆积顺序和与讨论相关的对象选择区域。根据图形中3个区域, MATLAB决 定哪一个回调将被激励。如果指针是在句柄图形对象内,如同对象的' Position'属性所确定的 那样,则指针就是在对象上。如果指针不在一个对象上,而在对象的选择区域内,则指针靠近 对象。如果指针在图形内但既不靠近也不在另一对象之上,则可以认为指针关掉其它对象。如 果若干对象及其选择区域相重叠,重叠顺序就决定了选择顺序。 句柄图形的线、曲面、补片、文本和坐标轴对象的选择区域已在上一章讨论过了 yimeng对象没有外部的选择区域,指针要么在 yimeng上,要么不在其上。 uncontrol对象越过 图基位置,在各方向延伸大约5个象素有一个选择区域,指针可以靠近或在控制框上。记住这 里讨论的堆积顺序和选择区域是针对42c版本的,在以后的MA卫LAB有某种程度的变化 按钮点击 按钮点击可以定义为当鼠标指针在同一对象上时,揿下并随后松开鼠标按钮。如果鼠标指 针在 uncontrol或 yimeng项上,按钮点击触发对象' Callback'属性字符串的执行,按钮揿下使 控制框作好准备,并常常在视觉上改变 uicontro或 yimeng,松开按钮触发回调。当鼠标指针不 在 uicontro或 uimeun上,揿下按钮和松开按钮事件,将在后面讨论 揿下按钮 当鼠标指针位于一个图形窗口内,揿下鼠标按钮,根据指针位置和对句柄图形对象靠近程 度将会发生不同的动作。如果一个对象被选择,它就变成了当前的对象,并上升到堆积顺序的 最高端。如果没有对象被选择,图形本身就是当前对象,图形的· Currentpoint·和 Selection Type’属性都被更新,然后激发适当的回调。表格21.3列出了指针位置与按钮揿下所 激发的回调: 表21.3 指针位置 所激发的属性 在umem或 t0项上面 准备释放事件 在句柄图形上,或接近控制柜 图形的 Window Button Down Fcn属性,然后是 对象的 Button Down Fcn属性
就无效果,因为在tpos2重新定义之前,通过计算tpos2,回调字符串已经建立。 21.6 指针和鼠标按钮事件 GUI函数利用鼠标箭头的位置和鼠标按钮的状态来控制MATLAB行动。本节讨论指针、对 象位置和鼠标按钮动作之间的交互,以及MATLAB如何响应变化或事件,诸如:揿下按钮、 松开按钮或箭头移动等。 回调属性,选择区域和堆积顺序 所有句柄图形对象具有一个至今还未阐述过的 ' ButtonDownFcn ' 属性,本节就进行讨 论。uimenu和uicontrol均有 ' CallBack ' 属性,这个属性是菜单和控制框的应用核心。另外, 图形有 ' KeyPressFcn ' 和 ' ResizeFcn ' 属性以及 ' WindowButtonUpFcn ' 和 ' WindowButtonMotionFcn ' 属性。与这些属性相关的值是回调字符串,即MATLAB字符串, 当属性激活时,它传给eval。指针的位置确定事件涉及到哪些回调以及当事件发生时它们被激 励的顺序。 前一章讨论过堆积顺序和与讨论相关的对象选择区域。根据图形中3个区域,MATLAB决 定哪一个回调将被激励。如果指针是在句柄图形对象内,如同对象的 ' Position ' 属性所确定的 那样,则指针就是在对象上。如果指针不在一个对象上,而在对象的选择区域内,则指针靠近 对象。如果指针在图形内但既不靠近也不在另一对象之上,则可以认为指针关掉其它对象。如 果若干对象及其选择区域相重叠,重叠顺序就决定了选择顺序。 句柄图形的线、曲面、补片、文本和坐标轴对象的选择区域已在上一章讨论过了。 uimenu对象没有外部的选择区域,指针要么在uimenu上,要么不在其上。uicontrol对象越过 图基位置,在各方向延伸大约5个象素有一个选择区域,指针可以靠近或在控制框上。记住这 里讨论的堆积顺序和选择区域是针对4.2c版本的,在以后的MATLAB有某种程度的变化。 按钮点击 按钮点击可以定义为当鼠标指针在同一对象上时,揿下并随后松开鼠标按钮。如果鼠标指 针在uicontrol或uimenu项上,按钮点击触发对象 ' Callback ' 属性字符串的执行,按钮揿下使 控制框作好准备,并常常在视觉上改变uicontrol或uimenu,松开按钮触发回调。当鼠标指针不 在uicontrol或uimeun上,揿下按钮和松开按钮事件,将在后面讨论。 揿下按钮 当鼠标指针位于一个图形窗口内,揿下鼠标按钮,根据指针位置和对句柄图形对象靠近程 度将会发生不同的动作。如果一个对象被选择,它就变成了当前的对象,并上升到堆积顺序的 最高端。如果没有对象被选择,图形本身就是当前对象,图形的 ' CurrentPoint ' 和 ' SelectionType ' 属性都被更新,然后激发适当的回调。表格21.3列出了指针位置与按钮揿下所 激发的回调: 表21.3 指针位置 所激发的属性 在uimenu 或uicontro项上面 准备释放事件 在句柄图形上,或接近控制框 图形的WindowButtonDownFcn属性,然后是 对象的ButtonDownFcn属性
在图形内,但不在或接近任何对象 图形的 Window ButtonDown Fcn属性,然后是 图形的 Button down Fen属性 注意:按钮揿下事件总是在所选对象的· Button downFcn’回调之前,引起图形的 Window ButtonDownFcn’回调,除非指针是在 contro或 yimeng对象上。如果指针靠近控制 框,则在图形的 Window button DownFen’回调完毕后,引起控制框的' Button DownFen回 调而不是' Callback’属性回调 按钮松开 当松开鼠标按钮时,图形的’ Currentpoint!属性就更新。如果没有定义 Window ButtonUpFcn'回调,则鼠标按钮松开时,属性' Currentpoint不更新 指针的移动 当指针在图形内移动时,图形的 Currentpoint’属性被更新,引起图形的 Window Button Motion Fen'回调:如果没有定义图形的' Window Button Motion Fen’回调,则 指针移动时,属性' CurrentPoint不更新 回调的复合能产生许多有趣的效应。试一下包含在 MATLAB于demo目录中的函数 sigdemol, sigde mo2,就可解其中的一些效果。另外将要讨论的一个例子是精通 MATLAB工 具箱的函数 redraw 21.7中断回调的规则 一旦回调开始执行,通常都在下一个回调事件处理之前运行完毕。将’ Interruptible'属 性设置为'yes’可改变这种缺省行为,从而当正在执行的回调遇到 drawnow, figure, getframel或 pause命令时,允许处理的回调事件悬挂起来。事件队列执行计算操作或设置对象 属性的命令一经发出,MA∏LAB便进行处理:而涉及图形窗口输入或输出的命令则生存事 件。事件包括产生回调的指针移动和鼠标按钮动作,以及重新绘制图形的命令。 回调处理 回调在达到 drawnow, getframe, pause或 figure命令之前一直执行。注意gcf和gea引起 figure命令,而精通 MATLAB工具箱中的函数 mmgef和 moca不引发 figure命令。不含有这些 特殊命令的回调不会被中断,一旦达到这些特殊命令之一,停止执行回调,将其悬挂起来;并 检查事件队列中每一个悬挂的事件。如果产生悬挂回调的对象的 interruptible属性设为’yes ,则在被悬挂的回调恢复之前按序处理所有悬挂。如果 Interruptible属性设为'no',即缺省 值,则只处理悬挂的重画事件,放弃回调事件。 防止中断 即使正在执行回调是不能被中断的,当回调达到 drawnow, figure, gefframe或 pause命 令时,仍然处理悬挂的重画事件。通过避免在回调中使用所有这些特殊命令,消除此类事情 如果回调中需要这些特殊命令,但又不要任何悬挂事件,甚至是刷新事件,来中断回调,则可 以使用如下所讨论的特殊形式的 drawnow Drawnow
在图形内,但不在或接近任何对象 图形的WindowButtonDownFcn属性,然后是 图形的ButtonDownFcn属性 注意:按钮揿下事件总是在所选对象的 ' ButtonDownFcn ' 回调之前,引起图形的 ' WindowButtonDownFcn ' 回调,除非指针是在uicontrol或uimenu对象上。如果指针靠近控制 框,则在图形的 ' WindouButtonDownFcn ' 回调完毕后,引起控制框的 ' ButtonDownFcn ' 回 调而不是 ' Callback ' 属性回调。 按钮松开 当松开鼠标按钮时,图形的 ' CurrentPoint ' 属性就更新。如果没有定义 ' WindowButtonUpFcn ' 回调,则鼠标按钮松开时,属性 ' CurrentPoint ' 不更新。 指针的移动 当 指 针在 图形 内移 动时 ,图 形的 ' CurrentPoint ' 属性 被更 新, 引起 图形 的 ' WindowButtonMotionFcn ' 回调;如果没有定义图形的 ' WindowButtonMotionFcn ' 回调,则 指针移动时,属性 ' CurrentPoint ' 不更新。 回调的复合能产生许多有趣的效应。试一下包含在MATLAB于demo目录中的函数 sigdemo1,sigdemo2,就可解其中的一些效果。另外将要讨论的一个例子是 精通MATLAB工 具箱的函数mmdraw。 21.7 中断回调的规则 一旦回调开始执行,通常都在下一个回调事件处理之前运行完毕。将 ' Interruptible ' 属 性设置为 ' yes ' 可改变这种缺省行为,从而当正在执行的回调遇到drawnow,figure, getframe或pause命令时,允许处理的回调事件悬挂起来。事件队列执行计算操作或设置对象 属性的命令一经发出,MATLAB便进行处理;而涉及图形窗口输入或输出的命令则生存事 件。事件包括产生回调的指针移动和鼠标按钮动作,以及重新绘制图形的命令。 回调处理 回调在达到drawnow,getframe,pause或figure命令之前一直执行。注意gcf和gca引起 figure命令,而精通MATLAB工具箱中的函数mmgcf和mmgca不引发figure命令。不含有这些 特殊命令的回调不会被中断,一旦达到这些特殊命令之一,停止执行回调,将其悬挂起来;并 检查事件队列中每一个悬挂的事件。如果产生悬挂回调的对象的Interruptible属性设为 ' yes ' ,则在被悬挂的回调恢复之前按序处理所有悬挂。如果Interruptible属性设为 ' no ' ,即缺省 值,则只处理悬挂的重画事件,放弃回调事件。 防止中断 即使正在执行回调是不能被中断的,当回调达到drawnow,figure,gefframe或pause命 令时,仍然处理悬挂的重画事件。通过避免在回调中使用所有这些特殊命令,消除此类事情。 如果回调中需要这些特殊命令,但又不要任何悬挂事件,甚至是刷新事件,来中断回调,则可 以使用如下所讨论的特殊形式的drawnow。 Drawnow
Drawnow命令迫使 MATLAB更新屏幕,只要 MATLAB回到命令提示,或执行dr ure, getframe或 pause命令,屏幕就更新。 drawnow的特殊形式 draunow(' discard')使事件 队列中所有事件的放弃。在回调中将 drawnow(’ discard’)包含在一个特殊命令之前,就含有 清除事件队列的效果,防止刷新事件,以及回调事件中断回调。 21.8M文件举例 精通 MATLAB工具箱中一些函数阐明了上面所讨论的若干技术。第一个例子 mmview3d应 用全局变量和递归函数调用,把方位角和仰角滑标加到图形中。函数中有大量的对象,但函数 很直观。因为 mmview3d文件相当得长,故分段表示。第一段定义了函数标号,帮助文本和全 局变量 MMVIe3d GUI controlled 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 callback Copyright(c)1996 by Prentice-Hall, Inc global Hc acur Hc esli Hc ecur CVIEW 第二段处理初始用户的调用,建立必要的 uncontrol对象并把回调定义为递归函数调用 %o Assign a handle to the current f window Get the current view for slider values Use normalized uncontrol units rather than the default ' pixel Hf fig=gcf CVIEW=get(gca,'View); if abs(CVIEW(I))180, CVIEW(1)=CVIEW(1)-(360*sign(CVIEW(I)): 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 He asli-uicontrol(Hf fig,'style,slider position',[.09.02.3.05], CVIEW(I), callback,'mmview3d(991));
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) ' );