转载自 落落轻尘
[Fig文件方式,即使用菜单File->New->GUI来设计界面]
首先值得注意的是,在低版本matlab上制作的含GUI的m文件一般不能在高版本的matlab上面运行,但是从7.0版开始改进了一点,我试过 6.5版的含GUI的m文件可以在 7.0版上运行,但如果在7.0版上面修改过.fig文件,那么就不能回到6.5版上运行了(显示一堆错误,我没看懂,不知道能否通过修改使之重新可在 6.5版上运行,呵呵),而在7.0版上制作的含GUI的m文件就完全不能放到6.5版上运行了(也是同样的错误)。这可能是因为matlab各版本在 GUI上改动较大,所以都不支持向下兼容。也许兼容性差是使用GUI编写程序的最大麻烦。
其次,说说使用GUI的好处。不知道是否承袭了VC or BCB的习惯,我比较喜欢编写完程序后按快捷键运行(此时会自动保存m文件),但是,对于程序有输入参数的时候,如果不采用GUI方式,这显然是行不通的――当然了,可以在command window按“向上”键然后重新改写你想要的参数。对于一些较大型的程序,正因为我比较偏向于按F5运行程序,所以我会选择使用GUI方式。不过GUI 方式的好处就远不止于此了,它可以把几个功能相关的模块集中起来,使得不需要重新关闭、运行就能得到不同的结果,便于比较;可以减少figure满天飞的 现象,这在matlab中尤为明显;便于交互式地观看不同的数据,例如在我处理的fMRI问题中,希望观看每个三维点对应的时间序列,这时候需要提供交互 式的选择……不过,尽管GUI有很多好处,但是其缺点也是有的,除了上面提到的兼容性(移植性)以外,要管理、维护一个GUI界面也是比较麻烦的,相信有 其他语言的界面设计经验的朋友也知道这点。
再者,对GUI问题,说说我的一点经验吧。其实,matlab已经在这方面改进了不少,从控件的增加和教程的学习都可以看出来。例如6.5版本是没有Panel和Button Group这两个控件的,在2006a版本中就新增了这两个控件(这个好像7.0版就有了,不确定);教程方面,也使用了最为直观的视频教学方式,建议新手看看Creating a GUI with GUIDE 和Creating Graphical User Interfaces两节。所以,操作上的细节我就不多讲了,自己摸索一下就ok了。
[转cwit]关于参数传递的方法:
1. 在内存中提取:
2. 存在硬盘上,采用save和load;
3. 用全局变量,最次的办法,有时却是最好的办法;
我想,对于这里处理的GUI问题,一般不会用到save和load命令(要从mat文件读取数据初始化或者把数据存储到mat文件中例 外),“function的varargin和varargout传送”的方法也不较少使用(因为对于控件的回调函数,matlab规定了输入参数为 “hObject, eventdata, handles, varargin”,且一般没有返回值,所以不同于自定义的函数),所以剩下的方法就只有三种了:
1. 存在handle的ApplicationData中――利用setappdata函数将数据保存在对象的“ApplicationData”属性中,利 用getappdata函数从对象的“ApplicationData”属性中提取数据,如果没有定义,就为空。例如,假设figure的tag属性是 figure1,则setappdata(handles.figure1,’A’,A)就可以把变量A存放到figure1的 “ApplicationData”属性中,名字为A,而B = getappdata(handles.figure1,’A’)就可以把figure1的“ApplicationData”属性中名字为A的变量赋给 B。setappdata和getappdata操作的对象,最好为figure_handle,便于管理和扩展。Matlab的高级编程和对象控制,将 大量使用这两个函数[转自cwit];
至于其他有关GUI命令、控件属性和图形属性可以参考matlab的帮 助,或者参考“GUI命令大全”、《精通GUI图形界面编程》(这两个本论坛有)、“Matlab图形图像属性”、“GUI.rtf”(这两个参见附件, 后者下载后手动修改一下后缀名)。实际上,用得比较多的控件属性不外乎以下几种(高手例外):
Visible属性,例如axes、edit、button等,格式:set(handles.***, ‘Visible’, ‘on’); 或者set(handles.***, ‘Visible’, ‘off’);
String属性,例如edit、text等,格式:str=get(handles.***, ‘String’)或set(handles.***,’String’,str);
Enable属性,例如edit、button、text等,格式:set(handles.***, ‘Enable’, ‘on’);或者set(handles.***, ‘Enable’, ‘off’);
Value属性,例如radio button、check box等,格式:a=get(handles.***, ‘Value’)或set(handles.***,’Value’,1); 或set(handles.***,’Value’,0);
留意一下响应函数的注释部分,有时候会得到提示的。例如,我的 matlab 2007a 中,在设计界面上增加了 listbox 控件后,m 文件的对应回调函数处显示如下:
% --- Executes on selection change in listbox1.
function listbox1_Callback(hObject, eventdata, handles)
% hObject handle to listbox1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: contents = get(hObject,'String') returns listbox1 contents as cell array —— 这是该控件基本用法的一点提示
% contents{get(hObject,'Value')} returns selected item from listbox1 —— 这是该控件基本用法的一点提示
1. 当控件位置有重叠时,直接放置方式与程序描绘方式不兼容。直接放置方式是指在GUI设计窗口中放置axes控件,程序描绘方式是指在程序中利用plot、 subplot函数作图。经本人测试,在同一个fig文件中,先使用程序描绘方式把图形plot出来(此时直接放置的axes控件为不可见状态),后欲再 把直接放置的axes控件重新设置为可见状态时,如果通过这两种方式控制的axes位置有重叠,那么放置的axes控件句柄会莫名其妙消失,变成无效句 柄,即出现Invalid handle的错误(尽管其handle是有值的)。所以,在交替采用这两种方式的时候,其位置不能发生重叠。――其根本原因应该是第5点所说的
【以下转自newseee】
4. 设计GUI,mailab版本越高越好,bug少,功能全面。比如 uigeifile(还是uigetdir?记不清了。)在R12中就不支持。初始化时,加上版本判断。
5. axes物件不能放到其它物件之上!
6. axes没有Callback,但是可以在上面放一张图(image),可以有Callback。
7. windows和linux下 GUI会看起来不一样,为了兼容,字体改成default,Unit 的单位要用characters。
8. 动态图形是循环画出来的。打开figure的DoubleBuffer到on,可以避免图形的闪烁。记得要用axes(h)。因为每plot一次,坐标系就刷新了。人不能踩进同一条河里。
9. matlab r13 有bug,linux下submenu不能动态更新,能删除,不能添加。我的解决办法是在callback中把GUI都关闭,然后更新submenu (在主函数中 function varargout = untitled_OutputFcn(hObject, eventdata, handles) 这一行下面添加,此时窗口还没有创建。),然后重新打开gui。
[m文件方式设计界面]
这种方式的入门最好根据自己的需要,下载一些具体例子作为参考(例如振动 或仿真等论坛上一些牛人发的帖子),结合手头上的任务(或者兴趣)来学。与上面的fig文件方式相比,这种方式可以夸不同的matlab平台使用,不必考 虑兼容性问题(当然了,要满足一个前提:要该平台的语法或命令支持才行,例如&&在6.5版本无效,也就是说,如果你的程序是用7.0以 上版本的matlab编写,但是希望程序可以在6.5版本中运行,那么在编写条件判断语句时只能使用&),但是换来的代价是所有控件的创建和布 局、事件的响应函数入口等等都需要自己用代码来实现,因此比fig文件方式要困难一点。当然,你可以下载别人写好的界面来做修改。一般来说,如果是用来内 部调试、测试的话,用fig方式比较好,但是如果用来向外发布的话,还是m文件方式比较通用一点(虽然可以打包来换取多一点的通用性,但你总不能带着 100多m的MCRInstaller文件到处走吧?2006b是100多m,2006a好像是60多m,记不清了)。
1. 建立控件时,直接采用“'属性名','属性值'”的方式(如'CallBack','delete(gcbf);clear all;abc()')将导致程序不能调试到达其响应函数(貌似调用自己时不能,调用其他函数可以,没有完全测试,呵呵), 解决方法是使用消息传递,即'CallBack’, @Action,然后写:
Function Action(hObject,eventdata,handles)
delete(gcbf);
clear all;
abc();
2. 实现进度条有两种方式(可能不止):waitbar方式和uicontrol方式,后者可以使用两个edit控件,或者使用axes控件加上line函数 生成,但是无论哪种方式,如果每次循环都刷新一下,那么当循环总次数很大时(如几十万次),运行速度会减慢,建议每隔一段距离(step)刷新一次,这样 可以加快运行速度。例如:
if (i - 100*k/N) <= 1e-003
waitbar(k/N);
i = i + step;
end
其中i是控制进度条在何处刷新,k是程序的循环变量,N是程序循环的总次数。
使用 uicontrol 方式实现进度条的示例:
复制内容到剪贴板
代码:figure;
e1 = uicontrol(gcf,'style','edit','BackgroundColor','w',...
'unit','normalized','position',[0.35,0.6,0.02,0.25]);
e2 = uicontrol(gcf,'style','edit','BackgroundColor','r',...
'unit','normalized','position',[0.3525,0.6,0.015,0.01]);
drawnow;
n = 1000;
ii = 1;
for i = 1:0.01:n
if (ii - 100*i/n) <= 1e-003
set(e2,'position',[0.3525,0.6,0.015,0.01+0.24*i/n]);
drawnow;
ii = ii + 1;
end
end【附录】转自cwit兄:
m文件与fig文件创建figure的十大差异——用代码写figure,并不是麻烦。如果你习惯了,或者熟悉了,会发现用代码实现guide编程,比GUI方便很多,功能也很强大。 用m文件实现guide编程,相比GUI编程有几大差异:
1. 代码可复用,节省成本;
2. GUI不能灵活创建uimenu,并且不能编辑其所有属性;
3. GUI还没有实现创建uitoolbox;
4. GUI不能创建所有axes的子对象;
5. 写界面也有一些算法,在GUI中无法实现。而用m文件就可以实现在不同窗口尺寸下给对象以合适的位置;
6. m文件可以生成非常复杂的界面;
7. 采用GUI编程,代码编译后依赖于*.fig文件;
8. m文件可以实现组件;
9. m文件创建的对象,可以方便的在handle中存取数据;
10.m文件可以将创建对象代码与动作执行代码很好的结合起来。
【注】关于两种方式的运行:
对于fig文件方式:fig文件记录的是控件的布局和属性等资源信息,m 文件记录的是控件的响应消息(这是个人理解,更准确的介绍请参阅有关GUI的书籍,我懒得去查了,呵呵),两者缺一不可。所以,不能通过打开fig文件 (如菜单中的Open命令)来运行该GUI,这种方式的运行方法有两种:打开该GUI对应的m文件,然后像普通m文件那样运行;打开该GUI的设计界面 (菜单操作:FileàNewàGUIàOpen Existing GUI,打开 fig 文件。