分享

阿英讲多个matlab gui之间的数据传递

 maoj66 2014-05-16

1 为什么要多个GUI之间参数传递?
      在matlab编写GUI界面时候,我们要很多个界面,例如 figA和figB,figA中的一个按钮来打开figB,当需要在figB中设置一些参数,然后把那些参数值返回给figA中的按钮的那个callback,以在figA中使用figB传过来的数据。"为了这个整了好几天头都了。今天终于看到希望了 哈哈 ,做个备注。"   ------ 首先感谢原作者无私分享他的知识,是你节省了我的学习时间。
2 缘起
      昨天在网上看了好多帖子,好多前辈都是把他成功的经验分享了一下,没有给具体的多个GUI之间数据传递的例子,或者举的例子没有详细的说明核心的参数传递机制。这给初学者带来了学习的瓶颈,增加了入门难度。此文的宗旨在于详细介绍多GUI之间数据传递的原理,结合实际例子深入浅出的把GUI参数传递的方法教给需要这方面知识的人。愿大家得大智慧,发无上心!
3 正文
       依次实践了下网上流传的多个GUI之间数据传递方式,我个人感觉好用的由以下三种方案,同时也推荐大家在实际的项目中使用,因为根据软件工程的思想不会影响整个工程的质量。下面依次介绍
(1) 思想:采用setappdata, getappdata 在子GUI中传递数据,通过 varargout 将子GUI的参数传递给主GUI,uiwait(指定句柄), 通过uiresume(指定句柄)返回OutputFcn。
方法:
1)主GUI中放一个Button,无参数调用子GUI,其CallBack如下
function pushbutton1_Callback(hObject, eventdata, handles)
mySettings = Gui2;
set(handles.text1,'string',mySettings.weight)
2)子GUI的figure的tag为figB,设置GUI子程序的OpeningFcn函数的结尾加上uiwait(handles.figB),这是因为在子GUI的OpenFcn中,如果不加uiwait, 程序会直接运行到下面,执行OutputFcn。也就是说程序一运行,返回值就确定了,再在其它部分对handles.output作更改也没有效果了。
function Gui2_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
% UIWAIT makes Gui2 wait for user response (see UIRESUME)
 uiwait(handles.figB);
3)在子GUI的pushbutton1的callback中加入如下代码,实现参数设置
spec_data.length = 20;
spec_data.weight = 200;
setappdata(handles.figB,'settings',spec_data); %如果保存数据到 0 句柄,即保存到 matlab 主程序,这类似于全局变量了
uiresume(handles.figB);  % 注意完成了参数设置后然后再uiresume,网上好多帖子都故弄玄虚,没讲明白。其实就这么简单
4)在子GUI的OutputFcn中加入如下代码,实现参数返回
function varargout = Gui2_OutputFcn(hObject, eventdata, handles)
% varargout{1} = handles.output; %默认的被注释掉了
tmp =getappdata(handles.figB,'settings');
varargout{1}=tmp; %注意一个结构体中包含了很多参数,原来多个返回值可以放在一个结果体中
(2) 思想: uiwait(gcf), 通过关闭当前子GUI时自动resume,然后执行OutputFcn中返回值的语句。其实要说明的是,此方法把参数放在handles = 0,不用varargout的话,在主GUI中getappdata(0,'settings');也可以直接获得settings的值。

方法:
1)主GUI中放一个Button,无参数调用子GUI,其CallBack如下
function pushbutton1_Callback(hObject, eventdata, handles)
mySettings = Gui2;
set(handles.text1,'string',mySettings.weight)
2)子GUI中的pushbutton1的callback中加入如下代码,实现参数设置
spec_data.length = 20;
spec_data.weight = 200;
setappdata(handles.figB,'settings',spec_data); %如果保存数据到 0 句柄,即保存到 matlab 主程序,这类似于全局变量了
% uiresume(handles.figB); 
3)子GUI中OpeningFcn函数的结尾不用加上uiwait(handles.figB),在OutputFcn的返回语句之前增加uiwait(gcf);
function varargout = Gui2_OutputFcn(hObject, eventdata, handles)
% varargout{1} = handles.output;
uiwait(gcf);  % 等待子GUI关闭后,然后自动resume,执行以下返回语句
tmp =getappdata(0,'settings');
varargout{1}=tmp;
(3)思想:通过varargin将主GUI的句柄传给子GUI,这样子GUI拥有了主GUI的句柄后就相当于VC++中View类中包含Doc类对象的指针一样,不用varargout,操作很方便额!该例子来自于matlab自带的Example:Manipulating a Modal Dialog Box for User Input
方法:
1)在主GUI中的OpeningFcn中,加入 uiwait(handles.figure),handles.figure中figure是主GUI的figure的tag
function changeme_main_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% Set waiting flag in appdata
setappdata(handles.figA,'waiting',1)
% UIWAIT makes changeme_main wait for user response (see UIRESUME)
 uiwait(handles.figA);
2) 在按钮的Callback函数中增加如下代码
function buttonChangeMe_Callback(hObject, eventdata, handles)
changeme_dialog('changeme_main', handles.figA);% 第二个参数是当前主GUI的句柄!
3)在主GUI的CloseRequestFcn中增加如下代码
function figure_CloseRequestFcn(hObject,eventdata,handles)
% Check appdata flag to see if the main GUI is in a wait state
if getappdata(handles.figA,'waiting')
    % The GUI is still in UIWAIT, so call UIRESUME and return
    uiresume(hObject);
    setappdata(handles.figA,'waiting',0)
else
    % The GUI is no longer waiting, so destroy it now.
    delete(hObject);
end
4)在子GUI中的OpeningFcn增加如下代码
function changeme_dialog_OpeningFcn(hObject, eventdata, handles, varargin)
% Is the changeme_main gui's handle is passed in varargin?
% if the name 'changeme_main' is found, and the next argument
% varargin{mainGuiInput+1} is a handle, assume we can open it.
dontOpen = false;
mainGuiInput = find(strcmp(varargin, 'changeme_main'));
if (isempty(mainGuiInput)) ...
    || (length(varargin) <= mainGuiInput) ...
    || (~ishandle(varargin{mainGuiInput+1}))
    dontOpen = true;
else
    % Remember the handle, and adjust our position
    handles.changeMeMain = varargin{mainGuiInput+1};  % 把主GUI的句柄保存到handles.changeMeMain字段
   
    % Obtain handles using GUIDATA with the caller's handle
    mainHandles = guidata(handles.changeMeMain);   %从主GUI的句柄guidata一下才能访问主GUI中的控件!
    % Set the edit text to the String of the main GUI's button
    set(handles.editChangeMe, 'String', ...
        get(mainHandles.buttonChangeMe, 'String'));
   
    % Position to be relative to parent:
    parentPosition = getpixelposition(handles.changeMeMain);
    currentPosition = get(hObject, 'Position'); 
    % Set x to be directly in the middle, and y so that their tops align.
    newX = parentPosition(1) + (parentPosition(3)/2 - currentPosition(3)/2);
    newY = parentPosition(2) + (parentPosition(4)/2 - currentPosition(4)/2);
    %newY = parentPosition(2) + (parentPosition(4) - currentPosition(4));
    newW = currentPosition(3);
    newH = currentPosition(4);
   
    set(hObject, 'Position', [newX, newY, newW, newH]);
end
% Update handles structure
guidata(hObject, handles);
if dontOpen
   disp('-----------------------------------------------------');
   disp('Improper input arguments. Pass a property value pair')
   disp('whose name is "changeme_main" and value is the handle')
   disp('to the changeme_main figure, e.g:');
   disp('   x = changeme_main()');
   disp('   changeme_dialog(''changeme_main'', x)');
   disp('-----------------------------------------------------');
else
   uiwait(hObject);
end
5)在子GUI中的buttonOK的callback增加如下代码
function buttonOK_Callback(hObject, eventdata, handles)
text = get(handles.editChangeMe, 'String');
main = handles.changeMeMain;   % 主GUI的句柄,就是varargin{2}
% Obtain handles using GUIDATA with the caller's handle
if(ishandle(main))
    mainHandles = guidata(main); %从主GUI的句柄guidata一下才能访问主GUI中的控件!
    changeMeButton = mainHandles.buttonChangeMe;
    set(changeMeButton, 'String', text);
end

uiresume(handles.figB);
6)其余部分的代码
% --- Executes on button press in buttonCancel.
function buttonCancel_Callback(hObject, eventdata, handles)
% hObject    handle to buttonCancel (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
uiresume(handles.figB);
% --- Executes when user attempts to close figB.
function figB_CloseRequestFcn(hObject, eventdata, handles)
% hObject    handle to figB (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
uiresume(hObject);
% --- Outputs from this function are returned to the command line.
function varargout = changeme_dialog_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figB
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
varargout{1} = [];
delete(hObject);

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多