zp2000 发表于 2009-10-23 09:51:43

使用GUIDE写界面时的变量调用(全局变量/局部变量)及示例

本帖最后由 messenger 于 2009-10-26 11:09 编辑

我是新手,尝试了下关于MATLAB下的GUIDE的操作,关于变量的作用范围问题想请教下大家,主要是关于edit text控件的

(1)在edit text的call back函数中,更新下来的貌似是个局部变量,其它函数要用的话,必须要采用全局变量共享,或者在其它函数内部调用get函数来直接获取值,这是否是说在edit text的call back函数中,更新下来的仅仅是该函数内部的一个同名的局部变量?
例如:function edit_speed_max_Callback(hObject, eventdata, handles)
         handles.speed_max = str2double(get(hObject,'String'));
该speed_max在其它函数内无法得到使用,是否是因为是局部变量?

(2)但我不明白的就是,同样也是个callback函数,类似于function FuzzyMap_OpeningFcn(hObject, eventdata, handles, varargin)这样在程序一开始就执行的opening函数,内部定义的变量为什么就没成为局部变量,而其它的模块可以使用它(例如一个push button的callback函数),这两者的区别在哪里?

新手提问,有什么错误的理解请大家见笑了。。。

ljelly 发表于 2009-10-23 10:52:05

不会是你以偏概全了吧
第一种情况是正常的,matlab调用函数所产生的变量值是存在于函数空间的,函数调用完毕后,内存
要释放数据,所以函数执行完后,数据就不存在了,也就是相当于局部变量的作用,其他函数无法使用

至于第二种情况,我还没碰到过,虽然没有全局变量,但gui之间数据的传递并非只有这一种方式
也许是用其他方式传递的参数,而你没有理解,能否把第二种情况的opening 函数和push button的callback函数代码贴一下,能全贴出来最好,便于查找,如果有不便,就贴下这两个函数的代码也可

zccbest 发表于 2009-10-23 10:56:32

加guidata就可以了

zp2000 发表于 2009-10-23 14:27:53

本帖最后由 zp2000 于 2009-10-23 14:39 编辑

感谢版主的细心解答,下面我先把代码贴出来,各位老大先看一看,我也感觉很疑惑下面这个是opening函数
% --- Executes just before FuzzyMap is made visible. function FuzzyMap_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to FuzzyMap (see VARARGIN)
handles.speed_min = -100;
handles.speed_max = 100;
handles.speed_number = 20;
handles.speedchange_min = -10;
handles.speedchange_max = 10;
handles.speedchange_number = 20;
handles.fuzzystruct = 'fuzzyspeed';
set(handles.edit_speed_min,'string',num2str(handles.speed_min));
set(handles.edit_speed_max,'string',num2str(handles.speed_max));
set(handles.edit_speed_number,'string',num2str(handles.speed_number));
set(handles.edit_speedchange_min,'string',num2str(handles.speedchange_min));
set(handles.edit_speedchange_max,'string',num2str(handles.speedchange_max));
set(handles.edit_speedchange_number,'string',num2str(handles.speedchange_number));
set(handles.edit_fuzzystruct,'string',handles.fuzzystruct);
% Choose default command line output for FuzzyMap handles.output = hObject;

下面这个是一个push button的callback函数
% --- Executes on button press in pushbutton_compute.
function pushbutton_compute_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_compute (see GCBO)
% eventdatareserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.speed_min = str2double(get(handles.edit_speed_min,'String'));
handles.speed_max = str2double(get(handles.edit_speed_max,'String'));
handles.speed_number = str2double(get(handles.edit_speed_number,'String'));
handles.speedchange_min = str2double(get(handles.edit_speedchange_min,'String'));
handles.speedchange_max = str2double(get(handles.edit_speedchange_max,'String'));
handles.speedchange_number = str2double(get(handles.edit_speedchange_number,'String'));
handles.fuzzystruct = get(handles.edit_fuzzystruct,'string');
handles.speed_x = linspace(handles.speed_min,handles.speed_max,handles.speed_number);
handles.speedchange_y = linspace(handles.speedchange_min,handles.speedchange_max,handles.speedchange_number);
disp(handles.speed_x);
disp(handles.speedchange_y);

问题就是:如果把上面红色部分的代码去掉,那么所有的变量值会采用在opening函数中写的初始值,而不是在edit text中的更新值(我在edit text的callback函数中也写了更新代码),始终没想明白这是怎么回事情

zp2000 发表于 2009-10-23 14:35:55

主要是打算做一个用来生成模糊控制表的程序,在MATLAB里面的模糊控制工具箱,貌似是无法自动生成输入和输出的表格的吧,只有一个surface viewer可以提供观察,但是啥变量也没有,问了好多人也没个结果,没办法才打算自己来写个东西的,现在还没写完,软件打算写成这样的界面吧:

以前是用VC写的程序,现在用了下MATLAB,呵呵,界面设计得不行啊,没啥功底,做起来很费力

ljelly 发表于 2009-10-23 16:56:16

本帖最后由 ljelly 于 2009-10-23 16:57 编辑

感谢版主的细心解答,下面我先把代码贴出来,各位老大先看一看,我也感觉很疑惑下面这个是opening函数
% --- Executes just before FuzzyMap is made visible. function FuzzyMap_OpeningFcn(hObject, eventdata,...
zp2000 发表于 2009-10-23 14:27 http://forum.simwe.com/images/common/back.gif
opening函数中设置的变量是放在句柄结构中的,并且赋给了初值
而你的push_button的callback函数中就是用红色代码获得的各个edit text
的值来更新这些变量,所以没有这些红色代码是完成不了更新的

你疑惑的应该是,没有红色代码的情况下,这些变量的值是在opening函数中
赋给的,为什么在push_button的callback函数中还保留着这些值?

这就是matlab GUI句柄结构的特点,存在句柄结构中的变量,是可以在GUI
各函数之间进行参数传递的,而不会消失,就像你在push_button的callback
函数中通过handles.edt_speed_min的属性值就可以获得该文本一样,是一种
参数传递的方式

zp2000 发表于 2009-10-23 18:03:43


opening函数中设置的变量是放在句柄结构中的,并且赋给了初值
而你的push_button的callback函数中就是用红色代码获得的各个edit text
的值来更新这些变量,所以没有这些红色代码是完成不了更新的

你疑惑的应该 ...
ljelly 发表于 2009-10-23 16:56 http://forum.simwe.com/images/common/back.gif
感谢版主的回答,我已经明白你的意思了,你是说因为变量是定义在句柄中,而句柄应该是可以在所有函数里共享的类似“全局变量”的东西吧,可是我还有一个疑问,就是为什么我在edit text中的callback函数中,也是用同样的方法给句柄的变量赋值,但是却无法完成更新,我测试的结果是如下的:
在一个edit text的callback函数中,有如下的语句:
function edit_speed_min_Callback(hObject, eventdata, handles)
% hObject    handle to edit_speed_min (see GCBO)
% eventdatareserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.speed_min = str2double(get(hObject,'String')) ;
disp(handles.speed_min);
% Hints: get(hObject,'String') returns contents of edit_speed_min as text
%      str2double(get(hObject,'String')) returns contents of edit_speed_min as a double
如上面所示,红色部分的代码的确是正确的执行了,并且也在MATLAB的命令行中给出了显示结果,这个显示结果也的确更新了(也就是我在GUI界面上输入的数值),问题是,在push button的callback函数中,却发现变量的值还是原来的结果,虽然edit text的callback函数中已经更新了值,但是push button内还是初始值,这个就是我的疑惑,所以我才认为在edit text中更新的只不过是个局部变量,因为在其它函数内部并没有改变值,而在edit text中的确是改变了

zp2000 发表于 2009-10-24 08:42:45

本帖最后由 zp2000 于 2009-10-24 11:28 编辑

先顶一下再说
同样的问题也存在于两个push button之间,在某个push button中定义的handles.xxx,在其它的push button中无法使用,系统给出提示说是不存在这个变量,我真叫个伤心啊!

目前用全局变量将就做着在,全局变量倒是方便,问题是理解上始终有个疙瘩

zccbest 发表于 2009-10-25 15:32:18

本帖最后由 zccbest 于 2009-10-25 15:35 编辑

就这么个问题整那么一堆干什么,在handles.xxx后面加
guidata(hObject,handles)更新handles就行了
另外最好用纯m文件编写,这样整个结构能更好的理解

zp2000 发表于 2009-10-26 09:38:15

本帖最后由 zp2000 于 2009-10-26 10:05 编辑

楼上兽王的兄弟的方法我试过了,的确是可行的,我在网上也查到了可以用这种方法来做到各个函数之间变量的共享,麻烦你能不能具体解释一下为什么要这样来更新啊?或者说下在MATLAB的help中哪个章节讲到了这部分的内容,我再仔细去看一看

zccbest 发表于 2009-10-26 10:13:21

handles是一个结构体,包含了figure上的所有控件,当然也包括figure本身
比如界面上有一个控件edit1,那么在别的地方调用可以用handles.edit1
我们可以往handles里面加入数值比如handles.a=0:10
然后利用guidata更新handles

风天小畜 发表于 2009-10-26 10:29:05

setappdata(h,'name',value)   保存某变量
value = getappdata(h,name)读取某变量

name,变量名,value 变量值
这个 h,可以是 你创建指定的图形句柄,如果懒得指定,你直接写gcf

zp2000 发表于 2009-10-26 10:29:05

本帖最后由 zp2000 于 2009-10-26 10:38 编辑

感谢兽王兄弟,大概明白了,handles应该是个全局变量,问题只是必须调用guidata才能来更新,我刚刚看了下simulink自动生成的程序,在opening函数中,果然在最后有
“% Update handles structure
guidata(hObject, handles);”
这条语句,终于明白为什么opening函数中的代码可以将变量的值更新而其它的函数不能了,就是其它函数缺少了这一句代码,这个应该类似于VC中的UpdateData这个函数的调用吧,兽王兄弟真强悍啦!

楼上兄弟的方法我也去试一试,看来传递变量的方法有很多啊!

zccbest 发表于 2009-10-26 10:50:48

handles并不是全局变量,因为handles只在当前figure有用,在别的figure里没法用的。
全局变量可以用 setappdata是也就是12楼说的
setappdata(h,'name',value)
value = getappdata(h,name)
当h为0 可以认为是全局变量
比如setappdata(0,appDataName,data);

风天小畜 发表于 2009-10-26 10:59:34

我把手头正在做的的一个GUI组件,精简一下,给你参考吧!!!

你可以试试手写,比较简单
GUIDE太罗嗦了













function mainQGui()

hMain_Win=figure('Color','k','MenuBar','none','Units','pixel','Name','amen@vip.sina.com','NumberTitle','off',...
    'Position',,'Resize','off','Toolbar','none','DockControls','off ','CreateFcn','movegui(''center'')','tag','main');
set(hMain_Win,'DefaultUicontrolUnits','pixel','DefaultUicontrolForegroundColor','w','DefaultUicontrolFontWeight','bold',...
    'DefaultUicontrolBackgroundColor','k');
hPanel01=uipanel('Parent',hMain_Win,'Units','pixel','BackgroundColor','k','ShadowColor','w','Position',,...
    'FontSize',12,'BorderType','etchedout','BorderWidth',1,'HighlightColor','r','BackgroundColor','k',...
    'ForegroundColor','r','Title','Info','tag','panel01','userdata',[-1 0 1]);
uicontrol(hMain_Win,'Position',,'FontSize',12,'Style','listbox','max',3,'min',1,...
    'String',{'aaa','bbb','ccc','ddd','eee'},'tag','list01','Callback',@list01Fcn);
uicontrol(hMain_Win,'Position',,'FontSize',12,'Style','listbox','max',3,'min',1,...
    'String',{'111','222','333','444','555'},'tag','list02','userdata',[-1 0 1],'Callback',@list02Fcn);
uicontrol(hMain_Win,'Position',,'FontSize',15,'Style','pushbutton','ForegroundColor','g',...
    'String','>>>>','tag','btn01','userdata',1,'Callback',@btn01Fcn);
uicontrol(hMain_Win,'Position',,'FontSize',12,'Style','pushbutton','ForegroundColor','r',...
    'String','Run','tag','btn02');
uicontrol(hMain_Win,'Position',,'FontSize',12,'Style','pushbutton','ForegroundColor','r',...
    'String','Restore','tag','btn03');
uicontrol(hPanel01,'Position',,'FontSize',15,'Style','pushbutton','ForegroundColor','r',...
    'String','X','tag','btn04','Callback',@slide_fade);
uicontrol(hMain_Win,'Position',,'FontSize',12,'Style','pushbutton','ForegroundColor','r',...
    'String','Reload','tag','btn05');
%{
在GUI creatFcn 的函数里添加
handles=guihandles;
if isempty(dir('Config01.mat'))
    tmpVar01=0;
else
    tmpVar01=load('Config01.mat','dInfo');
end
setappdata(handles.main,'numInfo',tmpVar01);

在相应的按钮等Fcn添加
handles=guihandles;
ppp=getappdata(handles.main,'numInfo');
还有,
save('Config01.mat','dInfo');
panel显示文本text,增加编辑按钮!编辑时显示edit控件
编辑完毕,保存到appdata,再保存config.mat
    %}
end

function slide_fade(hndVarBtn,datVar)
handles=guihandles;
hndVar=handles.panel01;
varStatu=get(hndVar,'userdata');
if varStatu(2)==1
    varStatu(2)=0;
    set(hndVar,'userdata',varStatu);
    return;
else
    varStatu(2)=1;
    set(hndVar,'userdata',varStatu);
end
btnPos=get(hndVar,'Position');
while(btnPos(2)<=10 && btnPos(2)>=20-btnPos(4))
    varStatu01=get(hndVar,'userdata');
    if varStatu01(2)==0
      varStatu01(3)= varStatu(3);
      set(hndVar,'userdata',varStatu01);
      return;
    end
    switch fix(rem(btnPos(2),3))
      case 0
            set(hndVar,'ForegroundColor','r');
      otherwise
            set(hndVar,'ForegroundColor','w');
    end
    set(hndVar,'Position',btnPos);
    drawnow;
    varStatu(3)=varStatu(3)+0.1;
    btnPos(2)=btnPos(2)+varStatu(3)*varStatu(1);
    pause(0.01);
end
if varStatu(1)==-1
    btnStr00='O';
else
    btnStr00='X';
end
varStatu(1)=-varStatu(1);
set(hndVarBtn,'String',btnStr00);
set(hndVar,'userdata',);
end

function list01Fcn(hndVar,datVar)
handles=guihandles;
set(handles.btn01,'String','>>>>','userdata',1,'ForegroundColor','g');
end

function list02Fcn(hndVar,datVar)
handles=guihandles;
set(handles.btn01,'String','<<<<','userdata',-1,'ForegroundColor','w');
end


function btn01Fcn(hndVar,datVar)
dirFlag=get(hndVar,'userdata');
handles=guihandles;
if dirFlag==1
    sourceHnd=handles.list01;
    tarHnd=handles.list02;
else
    sourceHnd=handles.list02;
    tarHnd=handles.list01;
end
sourceVal=get(sourceHnd,'Value');
sourceStr=get(sourceHnd,'String');
tarStr=get(tarHnd,'String');
kkk=length(sourceVal);
if isempty(sourceStr)
    return;
end
if isempty(tarStr)
    tarStr=sourceStr(sourceVal);
else
    tarStr(end+1:end+kkk)=sourceStr(sourceVal);
end
sourceStr(sourceVal)=[];
set(sourceHnd,'Value',1,'String',sourceStr);
set(tarHnd,'Value',1,'String',tarStr);
end

zp2000 发表于 2009-10-26 11:00:32

哦! -.-! 目前我也就写了一个fig,对handles的理解还很浅显,基本上能写程序了吧

zp2000 发表于 2009-10-26 16:13:51

感谢风天小畜老大提供的代码,我仔细看看先

juzi0210 发表于 2009-10-29 08:12:52

太感谢了!!!
页: [1]
查看完整版本: 使用GUIDE写界面时的变量调用(全局变量/局部变量)及示例