1 为什么要多个GUI之间参数传递?
在matlab编写GUI界面时候,我们要很多个界面,例如 figA和figB,figA中的一个按钮来打开figB,当需要在figB中设置一些参数,然后把那些参数值返回给figA中的按钮的那个callback,以在figA中使用figB传过来的数据。"为了这个整了好几天头都了。今天终于看到希望了 哈哈 ,做个备注。" ------ 首先感谢原作者无私分享他的知识,是你节省了我的学习时间。
2 缘起
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)
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;
handles.output = hObject;
guidata(hObject, handles);
% UIWAIT makes Gui2 wait for user response (see UIRESUME)
uiwait(handles.figB);
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,网上好多帖子都故弄玄虚,没讲明白。其实就这么简单
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; %注意一个结构体中包含了很多参数,原来多个返回值可以放在一个结果体中
% 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);
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;
% 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;
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
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);
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中增加如下代码
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
% 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.
% 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
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);
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
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);
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);
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);
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)
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);
delete(hObject);