其实 Matlab 提供了很多种直接或间接方法实现多 fig 中的数据共享,只是大家
没有注意罢了:
1、全局变量
2、作为函数的参数传递
3、利用控件的 userdata 数据
4、为 handles 结构体添加新字段
5、setappdata 函数为句柄添加数据
6、跨空间计算 evalin 和赋值 assignin
7、将数据保存到文件,需要时读取
8、带参数调用 GUI 的 M 文件
9、嵌套函数(不适用于 GUIDE 中,只适用纯命令是的 GUI)
一、全局变量
运用 global 定义全局变量传递参数,适用于 gui 内控件间以及不同 gui 间。这
种方式恐怕是最简单的方式,是很省心!但是,简单的问题就在于有时你会很头
疼!因为在每一个要到该全局变量的地方,你都要添一句 gloalx,还有就是如
果你在一个地方修改了 x 的值,那么所有 x 的值就都变了!有的时候恐怕会出
现紊乱。另一个更重要的问题在于,套用 C++的一句话,全局变量破坏了程序
的封装性!所以,全局变量是能少用尽量少用。
以下创造一个简单的 GUI 给大家说明一下,建一个 GUI, 包含两个按钮,一个
坐标系,一个用来画 y=sin(x),一个用来画 y=cos(x);
eg:在 GUI 的 OpeningFcn 函数中写:
globalx y1 y2
x=0:.1:2*pi;y1=sin(x);y2=cos(x);
在 pushbutton1_Callback 函数中写
Globalx y1
Plot(x,y1)
在 pushbutton1_Callback 函数中写
Globalx y2
Plot(x,y2)
全局变量是比较方便的,但全局变量会破坏封闭性,如果不是有大量数据要传递,
建议不要使用。
二、运用 gui 本身的 varain{}、varaout{}传递参数
这种方式仅适用于 gui 间传递数据,且只适合与主子结构,及从主 gui 调用子
gui,然后关掉子 gui,而不适合递进结构,即一步一步实现的方式。
输入参数传递(主要在子 gui 中设置):
比 如 子 GUI 的 名 称 为 subGUI, 设 想 的 参 数 输 入 输 出 为 : [out1,out2] =
subGUI(in1, in2)
在 subGUI 的 m 文件中(由 GUIDE 自动产生):
1.第一行的形式为:function varargout = subGUI(varargin)
该行不用做任何修改;varargin 和 varargout 分别是一个可变长度的 cell 型数
组。输入参数 in1 和 in2 保存在 varargin 中,输出参数 out1,out2 包含在
varargout 中;
2.在 subGUI 的 OpeningFcn 中,读入参数,并用 guidata 保存,即:
handles.in1= varargin{1};
handles.in2= varargin{2};
guidata(hObject,handles);
返回参数的设置:
1.在主 GUI 的 OpeningFcn 函数中加上[out1, out2] = subGUI(in1, in2),用于
调用子 gui,并在结尾加上 uiwait(handles.figure1);figure1 是 subGUI 的 Tag,
主要是等待调用子 gui 的过程,从而获得子 gui 的输出参数 out1、out2;
2.subGUI 中控制程序结束(如"OK”和"Cancel"按钮)的 callback 末尾加上
uiresume(handles.figure1),注意是主 gui 的窗口 handles.figure1,不要将
delete 命令放在这些 callback 中;
3. 在 子 GUI 的 OutputFcn 中 设 置 要 传 递 出 去 的 参 数 , 如 varargout{1} =
handles.out1 ; varargout{2}=
handles.out2; 末 尾 添 加
delete(handles.figure1); 结束程序。
在 GUI 的 OpenFcn 中,如果不加 uiwait, 程序会直接运行到下面,执行
OutputFcn 。 也 就 是 说 程 序 一 运 行 , 返 回 值 就 确 定 了 , 再 在 其 它 部 分 对
handles.output 作更改也没有效果了。
加上 uiwait 后,只有执行了 uiresume 后,才会继续执行到 OutputFcn,在此
之前用户有充分的时间设置返回值。
通过以上设置以后,就可以通过 [out1, out2] = subGUI(in1, in2) 的形式调用
该子程序。
在一个 GUI 中调用另一个 GUI 时,主 GUI 不需要特别的设置,同调用普通的函
数一样。在打开子 GUI 界面的同时,主程序还可以响应其它的控件。不需要担
心子 GUI 的返回值被传错了地方。
三、userdata 数据
直接通过对象的 userdata 属性进行各个 callback 之间的数据存取操作,主要适
用于 gui 内。首先必须将数据存储到一个特定的对象中,假设对象的句柄值为
ui_handle,需要存储的值为 value,则输入以下程序即可:
set('ui_handle','UserData',Value);
此时,value 数据就存在句柄值为 ui_handle 的对象内,在执行的过程中若要取
回变量可以通过以下方式在任意 callback 中获取该数据值 :
value=get(''ui_handle,'UserData');
虽然使用这种方法简单 ,但是每个对象仅能存取一个变量值,因此当同一对象
存储两次变量时 ,先前的变量值就会被覆盖掉,因此都用 UserData 存储简单
与单一的数据。如下面有两个 gui 函数, myloadfn 加载 mydata.mat 文件,
该文件内存储 XYData 变量,其值为 m*2 的绘图矩阵,加载后将该变量值存储
到 当前的窗口的 UserData 属性中。另一个 myplotfcn 函数则是用以获取该
UserData 属性中存取的绘图数据,然后绘图。代码如下:
function myloadfcn
load mydata;
set(gcbf,'UserData',XYdata)
function myplotfcn
XYdata=get(gcbf,'UserData');
x=XYData(:,1);
y=XYData(:,2);
plot(x,y);
userdata 的缺点就是一个句柄只能放一个 Userdata。
四、GUI 数据(handles)
结合 handles 和 guidata 函数,适用于 gui 内,如果你在 pushbutton1 中得到
一个变量 X,相传出去,那么在 pushbutton1 的 callback 中,在得到 X 后添加
如下代码:
handles.X=X;
guidata(hObject,handles)(注意,一定是两行连写)
在 pushbutton2 中要用到 X 是,在其 callback 先添加 X=handles.X; 即可
得到 X 的值。
注:
1. guidata(object_handle,data);如果 object_handle 不是 figure 型句柄,那
么会将 data 保存在 object_handle 的父 figure 对象中。这样不必担心在一个
pushbutton 的 callback 中存储的变量在其他对象中无法提取。
2. data = guidata(object_handle);获取当前 object_handle 的 handles 数据,
最后一次 guidata(object_handle,data)保存的数据。
一个简单的 GUI 给大家说明一下,建一个 GUI, 包含两个按钮,一个坐标系,
一个用来画 y=sin(x),一个用来画 y=cos(x);
eg:在 GUI 的 OpeningFcn 函数中写:
x=0:.1:2*pi;
y1=sin(x);
y2=cos(x);
handles.x=x;
handles.y1=y1;
handles.y2=y2;
guidata(hObject,handles);%注意,在 OpeningFcn 函数中这句是本身存在的,
若在其它函数中,务必加上这句
在 pushbutton1_Callback 函数中写
x=handles.x;
y1=handles.y1;
plot(x,y1)
在 pushbutton2_Callback 函数中写
x=handles.x;
y2=handles.y2;
plot(x,y2)
五、Application 数据
应用 setappdata\getappdata 与 rmappdata 函数,适用于 gui 间和 gui 内。
使用上面三个函数最有弹性处理数据的传送问题,与 UserData 的方式相类似,
但是克服 UserData 的缺点,使一个对象能存取多个变量值。
(1)getappdata 函数
value=getappdata(h,name)
(2)setappdata 函数
setappdata(h,name,value)
(3)rmappdata 函数
rmappdata(h,name)
首先在 matlab 命令窗口输入 magic(3)数据,因此当前的工作空间就存储了
magic(3)这组数据了,然后建立一个按钮来获取并显示 magic(3)数据。
A=magic(3);
setappdata(gcf,'A',A);%save
uicontrol('String','显示矩阵
A','callback','A=getappdata(gcf,''A'')');
A=