MATLAB学习笔记(二)——使用GUIDE构建App

使用MATLAB的GUIDE做简单的界面

GUIDE简介

GUIDE(Graphical User Interfaces Development Environment) 是由窗口、光标、按键、菜单、文字说明等对象(Objects)构成的一个用户界面。用户通过一定的方法(如鼠标或键盘)选择、激活这些图形对象,使计算机产生某种动作或变化,比如实现计算、绘图等。

在MATLAB的命令行窗口中键入guide可以打开GUIDE。这个命令将打开GUIDE Quick Start对话框。它可以看作是一个简单的GUI应用程序的开发向导。利用它可以使用鼠标方便地在窗体上添加各种各样的控件。而且它会负责生成一个m文件,里边定义了各个控件的回调函数,简化了GUI应用程序的开发。当然matlab中GUI应用程序也可以使用纯代码生成。在MATLAB中,关于guide的使用方法, 参见帮助文档:MATLAB/Getting Started/Create Graphical User Interfaces/Laying Out a GUI/Starting GUIDE条目下。

参考:https://baike.baidu.com/item/guide/3947857?fr=aladdin

其实目前MATLAB是不建议用户使用GUIDE来构建App的,MATLAB更推荐使用App设计工具来构建App
在这里插入图片描述
以后有时间了可能会写一些App设计工具的系列文章(先鸽着……)
更多构建App的方法,请参考App 构建

小例子

读取图片小栗子

实现了读取图片,使用一组复选框来使用不同的方法对图像进行边缘提取

功能实现

  1. 首先是搭界面

在这里插入图片描述

  1. 码代码:打开回调函数callback即可 首先是按钮‘选择图片’
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)
%选择图片路径
[filename, pathname] = uigetfile({'*.jpg';'*.bmp';'*.gif' },'选择图片');
%合成路径+文件名
str = [pathname, filename];
%读取图片
global im
im = imread(str);
%使用第一个axes1 即在axes1这个区域作图
axes(handles.axes1);
%显示图片
imshow(im)

然后是‘退出’按钮

% --- 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)
%关掉程序
close(gcf)

然后是按钮组 ,打开回调里面的SelectChangefcn,一个switch搞定

function uibuttongroup1_SelectionChangedFcn(hObject, eventdata, handles)
% hObject    handle to the selected object in uibuttongroup1 
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global im%使用全局变量im
str =get(hObject, 'string');%拿到按钮名称
axes(handles.axes1);%指定在此之后的作图都在这个axes1里面画图
switch str
    case '原图'
        imshow(im)
    case 'sobel)'
        BW = edge(rgb2gray(im), 'sobel');
        imshow(BW)
    case 'prewitt'
        BW = edge(rgb2gray(im), 'prewitt');
        imshow(BW)
    case 'canny'
        BW = edge(rgb2gray(im), 'canny');
        imshow(BW)
end

需要注意的是,要把读取的图片im 存为global全局变量,这样才能在两个函数之间调用。

结果展示:

在这里插入图片描述

成绩查询小栗子

功能实现

主要功能:在软件启动的时候,读取路径下的txt文件(里面存了一些学生的成绩),把学生姓名显示在左边的窗口,当用户点击姓名的时候,在右边窗口显示该学生的成绩。

首先是界面:

在这里插入图片描述

这里左边用了列表框,用来放读取到的数据 ,右边用到了可编辑文本,用来显示学生的成绩,上面的三个标签,用了静态文本。

代码:程序执行时 界面显示

%OpeningFcn 在程序执行功能的时候自动启动
function grade_OpeningFcn(hObject, eventdata, handles, varargin)

% Choose default command line output for grade
handles.output = hObject;

%以只读方式打开文件
fin = fopen('chengji.txt','r');
str = fgetl(fin);%返回文件中的下一行,并删除换行符
[str1 str2 str3 str4]= strread(str,'%s %s %s %s','delimiter',' ');%读取字符串 以空格作为分隔符
%四个标签暂时没用到
counter = 1;%用于计数
%读取名字 直到结尾(结尾返回1,循环结束)
while feof(fin) == 0
    str = fgetl(fin);%读取第二行
    [name yuwen shuxue yingyu] = strread(str,'%s %d %d %d','delimiter',' ');
    xingming(counter) = name;
    chengji(counter,:)=[yuwen shuxue yingyu];%给成绩的这一行赋值
    counter = counter + 1;
end
set(handles.listbox1,'string',xingming);%在listbox1显示内容
handles.chengji = chengji;%将成绩存入handles结构体,方便以后使用
set(handles.edit1,'string',num2str(chengji(1,:)));%默认显示第一个人的成绩
fclose(fin);%关闭文件

% Update handles structure
guidata(hObject, handles);

当用户选择姓名的时候,显示成绩:

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

value = get(hObject, 'value');%获取当前选项的索引值value 在本例中有五个人 每个人对应于一个索引值
set(handles.edit1,'string',num2str(handles.chengji(value,:)));

结果展示:

在这里插入图片描述

注意:在listbox的属性中, max 为用户依次可以选中的最大的元素数目。

读取Excle表格

功能实现

功能和上面那个差不多,不过这次可以手动选择文件,读取的文件为excle格式的,读取方式会有点区别。

界面设计:

在这里插入图片描述

多了个选择文件的按钮,和一个显示文件读取路径的窗口。

代码,首先是读取文件部分:

% --- 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)
%筛选文件类型为xlsx 和xls ,弹出的窗口的名字为chosse a file
[filename, pathname] = uigetfile({'*.xlsx';'*.xls'}, 'choose a flie');
%将文件路径保存下来
str = [pathname filename];

set(handles.edit2,'string',str);%显示文件路径及文件名字
xls_data = readcell(str);%以cell的形式读取excle文件
%在listbox1里面显示课程名字
set(handles.listbox1,'string',xls_data(2:end,1));
%在edit1里面显示第一门课对应的信息(类似于默认显示第一门的信息)
set(handles.edit1,'string', xls_data(2,:));
%将excle表格信息存到handles结构中,方便以后使用。
handles.xls_data = xls_data;
%更新guidata
guidata(hObject,handles);

可能是因为我的excle里面既有中文,又有数字,还有字符串,所以使用xlsread函数读取的时候,读取到是个空矩阵。使用readmatrix读取,所有的中文也都读取成了乱码。后来就使用了readcell进行读取,总算成功了。readcell牛逼!

然后就是listbox1的功能实现了:

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

value =get(hObject,'value');
set(handles.edit1,'string', handles.xls_data(value+1,:).');

显示效果:

在这里插入图片描述

总结:set()可以控制各个控件上面的显示,可通过handles.name进行索引,name就是控件的tap标签。

还有个小小的问题,就是使用readcell读取后的变量,用set显示的时候,好像只能显示成列,尽管我使用了转置,而且在窗口单独试了,转成列的数据依旧显示成行,怀疑是set函数的问题,这个有时间再深究一下。

还有就是要找个时间总结一下matlab里面的数据结构,类型,比如通过(){} []这三个括号对数据进行索引有什么区别。

改进

错误处理方式

对于用户的一些错误操作,进行一些判断,防止软件过于脆弱。

这里对用户的输入进行了判断,以及错误提醒。

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

[filename, pathname] = uigetfile({'*.xlsx','Excel Files(*.xls)';...
    '*.txt','Txt Files(*.txt)'}, 'Choose a flie');
str = [pathname filename];
set(handles.edit2,'string',str);
if length(filename)<5
    msgbox('您没有选择文件');
    return;
end
fname = filename(1,end-2:end);

switch fname
    case 'txt'
        fin = fopen(str,'r');
        counter = 1;%用于计数
        %读取名字 直到结尾(结尾返回1,循环结束)
        while feof(fin) == 0
            str = fgetl(fin);%读取行
            [name, yuwen, shuxue, yingyu] = strread(str,'%s %s %s %s','delimiter',' ');
            txt_data(counter,:)=[name yuwen shuxue yingyu];%给成绩的这一行赋值
            counter = counter + 1;
        end
        set(handles.listbox1,'string',txt_data(2:end,1));%在listbox1显示内容
        handles.data = txt_data;%将成绩存入handles结构体,方便以后使用
        set(handles.edit1,'string',txt_data(2,2:end));%默认显示第一个人的成绩
        fclose(fin);%关闭文件

        % Update handles structure
        guidata(hObject, handles);
            
    case 'lsx'
        xls_data = readcell(str);
        set(handles.listbox1,'string',xls_data(2:end,1));
        set(handles.edit1,'string',xls_data(2,2:end));
        handles.data =xls_data;
        guidata(hObject,handles); 
    otherwise
        msgbox('请选择正确的格式');
end

代码有点问题,以后有时间改改。

GUI的优化进度条

主要是 加了一个事件的进度条

 case 'lsx'
        xls_data = readcell(str);
        h = waitbar(0,'正在读取文件哦');%创建一个waitbar 0为当前进度
        pause(2)
        waitbar(1,h,'读取完毕')% 进度显示为1 
        close(h)%关闭进度条
        set(handles.listbox1,'string',xls_data(2:end,1));
        set(handles.edit1,'string',xls_data(2,2:end));
        handles.data =xls_data;
        guidata(hObject,handles); 
    otherwise
        msgbox('请选择正确的格式');

退出功能:

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

clc
clear all]
close(gcf);%gcf表示当前的GUI程序

程序打包及混合编程

首先是打包,进入有.fig和.m文件的路径中:输入

mcc -m untitled%untitled是guid的名字

然后生成了一个exe文件,还有一堆log文件。但是这个exe文件只有在装了matlab的电脑上运行,想在没有装matlab的电脑上运行,需要下载一个版本一致的matlab库函数MCRinstaller。

混合编程使用comtool

添加菜单active控件

这个因为版本问题,使用视频上的方法老是出错。

实现了播放视频的功能。

上代码:

第一种方法是通过proid和pos来建立activex(系统的视频控件)。

% 窗体打开前,执行该函数----------------------------------------------------
function playMTV_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;

pos=[0 0 0 0];
%MovieControl=actxcontrol('AMOVIE.ActiveMovieControl.2',pos);
%actxcontrol   get(MovieControl)  查看文档属性
MovieControl=actxcontrol('WMPlayer.OCX.7',pos);  %调用Windows的系统控件(activex控件)
handles.MovieControl=MovieControl;  %绑定到全局变量中
mp=handles.MovieControl.currentMedia;
handles.output=mp;

guidata(hObject, handles);


% 打开文件按钮,播放视频----------------------------------------------------
function Untitled_2_Callback(hObject, eventdata, handles)

[filename pathname]=uigetfile('*.*','选择媒体文件');   %打开文件对话框
if ~filename   %如果没有打开文件
    return;
end
url1=[pathname filename];  %拼接绝对路径
set(handles.MovieControl,'URL',url1);  %用MovieControl播放视频



% 窗体大小改变时,执行该函数------------------------------------------------
function figure1_SizeChangedFcn(hObject, eventdata, handles)

units=get(handles.figure1,'units');
set(handles.figure1,'units','pixels');   %将单位设置成像素
pos=get(handles.figure1,'Position');
set(handles.figure1,'units',units);
pos=[0 0 pos(3:4)];      
move(handles.MovieControl,pos);   %设置MovieControl控件的大小随窗体大小的改变而改变


% 退出按钮-----------------------------------------------------------------
function Untitled_3_Callback(hObject, eventdata, handles)

clc;
clear all;
close(gcf);

第二种是通过先把activex1拖进gui,然后通过Activex1这个tap来对视频控件进行操作(感觉所有的GUI控件都可以通过它的tag,使用set函数对它进行显示操作)。

% 窗体打开前,执行该函数----------------------------------------------------
function test_OpeningFcn(hObject, eventdata, handles, varargin)
%把activex1的currentMedia属性给mp
mp = handles.activex1.currentMedia;

% Choose default command line output for test
handles.output = mp;%将当前窗口的output属性设为mp

% Update handles structure
guidata(hObject, handles);%handles结构体里面包含hObject(即我们的这个GUi,figure1)的所有信息,更新的时候,handles对hObject负责,同步更新  hObject指该figure的句柄;
% 打开文件按钮,播放视频----------------------------------------------------
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)

[filename pathname] = uigetfile({'*.*'},'选择一个视频');
if ~filename
    return;
end
url = [pathname filename];
set(handles.activex1,'URL',url);
% 窗体大小改变时,执行该函数------------------------------------------------
function figure1_SizeChangedFcn(hObject, eventdata, handles)

units=get(handles.figure1,'units');
set(handles.figure1,'units','pixels');   %将单位设置成像素
pos=get(handles.figure1,'Position');
set(handles.figure1,'units',units);
pos=[0 0 pos(3:4)];      
move(handles.MovieControl,pos);   %设置MovieControl控件的大小随窗体大小的改变而改变

参考:https://www.bilibili.com/video/BV1Ut411y7uh

总结

要点:

hObject指该figure的句柄;

handles.output = hObject;
guidata(hObject, handles);

这两行代码配合使用,意思就是把该figure的句柄存到handles结构体中的output字段里去;

目的是使figue的主函数返回该figure的句柄,见OutputFcn函数:

varargout{1} = handles.output;

主函数负责调度各个控件的callback响应。

  • 10
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛定猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值