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); |
|