前言
接触图形界面已有一段时间,学习过python tkinter ,Pyq5学习一点,到最近由于课程matlab 作业的需要,摸索GUI操作。感觉各种东西在脑袋里混成一团浆水。说实话,老师课上基本没讲什么,大部分时间都是度娘和各种博客胡乱摸索了一通,总觉得查找的资料有点多,所以想综合下各方资料,同时也给学习一些参考。
内容
课程作业的其中一项内容:制作gui界面,可以选取文件夹,将里面的所有文件名都展示在listbox内;双击文件名,会显示图片,如果不是图片,会弹出提示。
1.step 图形界面的搭建
命令窗口 输入 guide 进入图形界面搭建。 左手边的按键,自己全部点一下就知道是什么样有什么功能。另外说一点就是,双击 控件 进入属性设置
以下就是我构建的一个图形界面的初始界面
2.step 功能实现。
首先分析怎么实现。
(1)打开文件夹:获取选择的文件夹路径,然后获取该路径下的所有的文件名,将文件名传给listbox显示出来。
(2)对于listbox 获取双击对象的文本内容,对文本进行判断,是图片就显示,否则出现报错信息
(3)清空 清空所有的输入,重置初始界面
分析完之后,先实现第一个功能。
(1)右键“打开文件夹”选择回调,进入回调函数设置。
语法:
- if …else…end(一定要用end来结束)
- for i=a:b do something end(一定要用end来结束)
- % 该行都是注释
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
handles.filepath = uigetdir('*.*','请选择文件夹') %得到了文件夹的路径
if handles.filepath %如果获得文件夹路径
filelist=dir(handles.filepath)
%获得文件夹下的所有文件 是一个6x1的struct结构。得到到filelist.name属性下获得的前两个是 ./ ../ 需要从第三个开始取
sizeof=size(filelist); % 总数-2就是子文件数量
len=sizeof(1);%得到个数
handles.list=cell(1,len-2)
%将子文件名内容保存到handles 下的list属性下,这样就能跨函数来调用数据。这里是以胞组的形式保存,因为每个文件名的字符串个数都不一样(这里踩过几次坑,每次就想到了python里的列表)
%遍历每个存储的内容,从3开始取。
%matlab的索引是从1开始的(取第几个就用数字几),python的索引是从0开始的,是不同的
for i=3:len
handles.list{1,i-2}=filelist(i).name %获得字符串的文件列表 胞组要用{} 花括号来索引
end
set(handles.listbox1,'string',handles.list) %列表框文件显示,整个胞组传进入
set(handles.text4,'string',handles.filepath) %同时显示当前选择的文件路径
%保存数据(这条命令要记住)
guidata(hObject,handles)
end
小总结:
- 1.用一个变量 来接收 dir ()返回值时是一个 struct 结构体,这和没有变量接收打印出来的dir() 内容很不一样。
- 2.其次接收后要获取文件列表要从第三个开始取 ,用cell存起来。
- 3.取cell内容要用{} 花括号。
(如果有更加优化的写法,可以在讨论区艾特我,新手上车,代码效率可能不高) - 4.关于listbox 存储的类型验证
MATLAB GUI 之 列表框 属性 ‘string’ 元胞存储
listbox 获值说明
GUI listbox的用法
(2)listbox的响应
右键该控件 选择回调进入
语法: try…catch exception …end 捕获异常,进行一个简单的异常处理
是通过捕获异常来控制 提示框 的输出
% --- 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 = cellstr(get(hObject,'String')) returns listbox1 contents as cell array
% contents{get(hObject,'Value')} returns selected item from listbox1
global clik
set=get(gcf,'selectiontype');%获取鼠标按键类型,因为是双击
if strcmp(set,'open')
%清空之前显示的图片
if clik
axes(handles.axes2)
cla()%清除画布
end
num=get(handles.listbox1,'value')%直接得到列表框的文本,这里要用'value'来获取 点击的项数 ,用‘string’获取的是整个胞组内容。当时上课漏了这个细节,绝望了一个下午。
%判断是否是图片
all=get(handles.listbox1,'string') %得到所有的文本内容
content=all(num) %取点击的对象 的文本
assignin('base','content',content) %使用assignin() 可以在运行的时候,在工作区里面查看改变量输出(十分好用的一个技巧),比直接输出还好,可以看到变量的结构信息
content=content{1,1} %上面获得是个胞组,所以要转换变成char 类型
try
result=regexpi(content,'.(jpg|png|jpeg)','match') %正则匹配
%matlab 打开的图片格式还有其他,可以在上面
result=result{1,1}%如果能够转,说明是图片,而不会报错(这里是引发异常的关键)
%我在这里用异常的原因是因为之前我获取的img_path是胞组类型。后来不知怎么又变成了char类型。所以预防了这种玄学的情况,我才用了异常处理(如果有知道什么原因导致可以在讨论区回复我)
try
img_path=strcat(handles.filepath,'\',content) %路径拼接
assignin('base','img_path',img_path)%监控信息 是个胞组(就是通过这里来监控img_path的类型,类型会害死人的)
% img_path=img_path;
axes(handles.axes2);
image=imread(img_path);
catch exception
img_path=img_path{1,1};
image=imread(img_path);
end
imshow(image)
clik=clik+1%只有执行完才算有效(我在上面是通过clik来控制是否清除)
assignin('base','clik',clik)
catch exception
warndlg('这不是图片,无法显示','warning string')
end
end
小总结:
1.正则匹配的内容:
Matlab正则表达式(递归、匹配上下文等)
图片、视频文件、音乐文件的正则表达式
关于matlab 三个正则表达式函数的具体说明
matlab正则表达式
- regexp——用于对字符串进行查找,大小写敏感;
- regexpi——用于对字符串进行查找,大小写不敏感;
- regexprep——用于对字符串进行查找并替换。
2.有一点我不是用的很好的就是全局变量的声明,我在进入主页面开始的时候声明了global 变量,但是到这里还是会报错,所以我又在这里又声明了一次全局变量。老师讲课的建议是她很少用global来声明,都是在handles 下新建一个属性来保存值的。
(3)清空部分
% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton2 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global clik
set(handles.listbox1,'string',[]) %设置空
set(handles.text4,'string',[])
if clik
% axes(handles.axes2)
% cla()%清除画布
% set(handles.axes2,'Color','w')
delete(allchild(handles.axes2))
set(handles.axes2,'Color','w')
end
清空部分有两种做法:
-
axes(handles.axes2) cla()%清除画布 set(handles.axes2,'Color','w')
-
delete(allchild(handles.axes2)) set(handles.axes2,'Color','w')
但是尽管用了set设置,背景色还是和主页面一致,没有变成白色(如果有什么方法可以设置,可以在讨论区留下你的方法,十分感谢)
最终效果
如果有什么好的想法,可以改进的地方,欢迎在讨论区留下你们的留言~