图形用户界面(GUI)开发教程

文章目录

  • 写在前面
  • MATLAB GUI启动方式
  • 按钮(Push Button)
    • 查看属性
    • `tag`的命名方式
    • 回调函数
    • 小小的总结
  • 下拉菜单(Pop-up Menu)
  • 单选框(Radio Button)和复选框(Check Box)
  • 静态文本(Static Text)和可编辑文本(Edit Text)
  • 轴(Axes)
  • 组(Group)
  • 进度条(Progress Bar)
  • GUI设计成品
  • 最后

写在前面

图形用户界面(Graphic user interface,GUI),实际上就是人与计算机交互的界面显示格式。广义来说,现在正在看这篇文章使用的浏览器,也是一个GUI。阅读者可以通过这个浏览器获取信息,可以点击“最小化”、“窗口”和“关闭”按钮实现自己想要的功能,可以阅读浏览器中的文字。

我们常说的做个“软件”,其实大概率是做一个实现与后端算法交互的界面。因为绝大多数用户看不懂后端代码,但又想使用这个算法实现自己想要的功能,所以做一个简明、整洁、易用、美观的GUI,对于提升后端算法的适用性是十分有必要的。

总不可能开发一个项目,把算法写好之后,直接给用户,说:“喏,这就是你想要的功能,你简简单单改几个参数就可以实现你想要的功能啦!”显然是不可行的。用户看见代码的时候只会感到头脑眩晕,开始抗拒,并且怀疑我们的代码能力到底行不行?

举个例子。

程序员小雷写了一套卡尔曼滤波算法,交付给用户的时候,是这样的:

mode = 'IF'; 
% mode = 'UD';
% mode = 'FD';
% mode = 'FT1';
% mode = 'FT2';

和用户说,“想要用信息滤波就取消mode = 'IF'的注释就可以啦!”

“想要用UD滤波就取消mode = 'UD'的注释就可以啦!”

……

“但别忘记把其他不想用的滤波算法给注释掉噢,不然会出bug的!”

用户听完小雷的介绍之后说不定就已经头脑发昏,也不知道什么算法要注释哪行代码了。

或者更加极端一点,小雷写代码也不规范,变量名乱写,比如这样:

aaa = '1';
% aaa = '2';
% aaa = '3';
% aaa = '4';
% aaa = '5';

天知道哪行对应哪个滤波算法啊!!

但如果写一个GUI呢,比方像下面这样简单的选择框:

在这里插入图片描述
是不是清楚好多?

用户也不用自己翻开后端算法的代码看来看去了,那样看半天说不定也看不出来门道。现在用户想要用什么滤波模式,自己选择想要的滤波模式,然后点击确定就可以啦。

不过这样的界面还没有满足用户的需要。

假如用户想自己改算法参数呢?想改改仿真时长啊初始状态啊噪声矩阵啊……上面的选择框显然没有提供合适的地方让用户可以改算法参数。

所以小雷又重新设计了一下界面,把它改成了下面这样:
在这里插入图片描述
现在给用户的选项可丰富啦。可以选择滤波模式,可以选择是否保存图片、数据,可以修改仿真参数,还可以显示不同滤波算法的核心原理公式,给用户直观的感性认识。广义来说这样就可以当作一个软件来用啦。

用户感到很满意。

所以,这样的界面怎么开发呢?

下面根据自己的实战经验,给出开发GUI的完整流程,或许会少掉一些控件不作介绍,因为觉得在自己开发过程中没有使用这些控件。但我觉得控件的使用方法大同小异,核心逻辑掌握之后,换另外一个控件只需要自己在网上搜索一下经验学习一下,很快就能掌握。

先说明,这里说的GUI全部指的是MATLAB 2018版本上的GUI,MATLAB后续版本中推出了APP功能,将原来的GUI替代了。但本人常用的软件还是MATLAB 2018,所以写的都是MATLAB 2018上GUI开发的教程。至于其他真的像个“软件”一样的教程,请见《PyQt5+Anaconda+PyCharm安装、配置和使用》(https://blog.csdn.net/Ruins_LEE/article/details/116279032)。使用QT可以做一个像“软件”的软件出来了。

下面是整篇教程的顺序:

  • MATLAB GUI启动方式;

  • 按钮:

    • 查看属性;
    • 回调函数;
  • 下拉菜单;

  • 单选框和复选框;

  • 静态文本和可编辑文本;

  • 轴;

  • 组;

  • 进度条;

  • GUI源代码。

MATLAB GUI启动方式

打开MATLAB,在命令行输入

guide;

得到下图所示界面。
在这里插入图片描述
这里我们选“新建 GUI”,点击第1项“Blank GUI (Default)”,选好要保存的位置后,点击“确定”。

之后会出现一个新的界面,如图所示。

在这里插入图片描述
按照图片中的分区一一介绍功能。

  1. 分区“1”中常用的按钮是最后一个绿色三角形,用于设计好GUI后运行,查看效果。其他的按键不常用,不用花费精力在上面。
  2. 分区“2”是控件区,给出了MATLAB GUI中可以使用的控件。我们在设计GUI时,常用的控件主要有(按照从上往下、从左往右的顺序):
    • 按钮;
    • 单选按钮;
    • 复选框;
    • 可编辑文本;
    • 静态文本;
    • 下拉菜单;
    • 轴;
    • 组;
      后面的内容里会一一介绍。
  3. 分区“3”说明了该GUI的标签(tag),在句柄(handles)操作中会用到。
  4. 分区“4”说明了当前鼠标的在GUI中的位置和选中控件的位置与尺寸。
    • 当前点: [369,451]意为鼠标在距离GUI(用figure1更加准确,但出于文章易读性考虑,使用GUI更易理解。后面提到的GUI均为figure1之义。)最左侧369像素、最下侧451像素的位置;
    • 位置: [760, 584, 567, 630]意为选中控件在距离父对象1最左侧369像素、最下侧451像素的位置;尺寸大小为宽度567像素、长度630像素。

按钮(Push Button)

查看属性

在功能区中选中“按钮”的标签,将其拖进GUI中。

在这里插入图片描述
第1步和第2步很简单,第3步需要左键双击“按钮”,弹出来“检查器”窗口。

检查器很重要啊,绝大部分操作都是在检查器里面完成的。
在这里插入图片描述
检查器有2种查看方式,在红框里面标出来了。第1种是按照功能分类列好,第2种是按照字母顺序列好。这里推荐使用第1种方式查看按钮的属性。需要关注的属性不多,只有4种,分别是:

  • Appearance:设定按钮的外观,比如背景颜色和文字颜色;
  • Font Style:设定按钮字体风格;
  • Identifiers:设定该按钮的标识,也就是tag
  • Text:设定按钮显示的内容。

把按钮美化一下,可以得到下图这样的按钮风格。

在这里插入图片描述
其余控件都是这样设置,在这里用按钮作为例子讲解一下,后面介绍其他控件的时候不再赘述。

tag的命名方式

多提一嘴tag这里该怎么设置。

将按钮拖进GUI后,tag默认为pushbutton1。这个tag不好,没有辨识度,将来控件多了之后不知道哪个tag对应哪个功能了,所以需要加上标识,方便以后阅读代码。

我自己的习惯是用下划线法命名tag,即“功能_控件标识”,这里按钮的tagsimu_btn,意思就是用于实现仿真的按钮。

其余控件命名原则如下:

  • 下拉菜单:xxx_ppmenu
  • 单选框:xxx_rbtn
  • 复选框:xxx_cbox
  • 静态文本:xxx_txt
  • 可编辑文本:xxx_edit
  • 轴:xxx_axes
  • 组:xxx_group

回调函数

选中按钮,单击右键,选中“查看回调”,再选中“Callback”,在MATLAB中会生成对应的回调函数。

在这里插入图片描述
MATLAB中会显示下图所示的代码。
在这里插入图片描述
这个功能很重要。

是实现所有我们想要开发功能的地方。因为一开始自己对GUI也是一头雾水,不知道要用GUI实现功能的话,要在什么地方写自己的逻辑。后来查了资料之后才知道——噢,要在回调函数里面写逻辑啊~

其他控件的逻辑也都是在相应的回调函数里面写,这点不要忘记,后面就不再提其他控件的回调函数怎么弄出来了。

小小的总结

总结一下,按钮(包括其他控件)的使用步骤分为3步:

  1. 将要用的控件拖进GUI中;
  2. 打开该控件的检查器,根据需要设置属性;
  3. 编写回调函数。

下拉菜单(Pop-up Menu)

下拉菜单和下拉列表(Listbox)作用差不多,但是下拉菜单更加节省空间。在项目GUI设计中,个人习惯用下拉菜单实现多个选项的逻辑。

它在GUI里面长这样:

在这里插入图片描述
图中的“选项1”、“选项2”、“选项3”和“选项4”要在检查器中设置。

在这里插入图片描述
也就是text中的string属性,一个选项一个回车键,这样就可以排列好。

设置好弹出式菜单的选项之后,很重要的一步就是怎么读弹出式菜单的选项?

代码在这里:

mode_flag = get(handles.filter_ppmenu,'value');

通过get()函数就可以取到弹出式菜单的值啦。这里我给这个弹出式菜单设的tagfilter_ppmenu,代码的意思就是获得句柄为filter_ppmenu的值(value)。

得到弹出式菜单的值之后,可以用switch()函数来选择相应的操作,代码如下:

switch mode_flagcase 1% 想要实现的功能case 2% 想要实现的功能case 3% 想要实现的功能case 4% 想要实现的功能case 5% 想要实现的功能
end

注意哈,mode_flag=1的时候,实际上就是默认选项的值,也就是弹出式菜单这个选项的值。mode_flag=2开始才是真正要选的选项的值,这一点很容易出错,要记住。

如果怕出错,可以在第1行不要弄什么弹出式菜单这样的值,直接写要选的选项就好。

单选框(Radio Button)和复选框(Check Box)

单选框是一个圆圆的可以选中的按钮,通常用来实现与其他功能互斥的选择功能。

复选框是方方正正的样子,通常用来实现多种功能选择的组合。

一般单选框选中之后就没法儿取消,或者选择这个选项之后,其他被选中的功能被取消;复选框则是选中这个功能之后,还可以继续选择其他的功能,而且被选中的功能是可以取消的。

它们长下图这样。

在这里插入图片描述
这俩框没有什么复杂的,要记住的地方就是它们在GUI中的作用就是获取它们的值。除了这个作用之外,其他的作用还没开发出来。

代码为:

% 单选框获取值的方式
xxx_rbtn_flag = get(handles.xxx_rbtn,'value');
% 复选框获取值的方式
xxx_cbox_flag = get(handles.xxx_cbox,'value');

静态文本(Static Text)和可编辑文本(Edit Text)

静态文本通常显示固定不动的标签,可编辑文本可以用来输入参数,这是两者功能的区别。它们俩分别长下面这样。

在这里插入图片描述
静态文本放在GUI里就不用动了,可以不去管它,要管的是可编辑文本。

获取可编辑文本中的文本,代码为:

xxx_edit_str = get(handles.xxx_edit,'string');
xxx_edit = str2double(xxx_edit_str);
% xxx_edit = str2num(xxx_edit_str);

这里的属性不能用value,要用string,因为得到是可编辑文本中的字符(string)。

如果要使用可编辑文本中的数值,需要先将字符转换为数值,用str2double()或者str2num()实现。

也可以设置可编辑文本中的值,一种方法是直接在可编辑文本框里设置,另外一种方式可以写代码,为:

set(handles.xxx_edit,'string','Hello, world!');

这样就可以设置可编辑文本的代码了。

轴(Axes)

轴,通常用来画仿真曲线图或者插入图片。

在这里插入图片描述
在之前的项目中用轴画过算法仿真曲线,代码为:

axes(handles.xxx_axes);
plot(xxx);

如果要清除轴上的图,可以用下面的代码。

axes(handles.xxx_axes);
cla;

可以看到不论是画仿真结果还是清除结果都要先用axes(handles.xxx_axes),这行代码意思是指定对应的轴。如果一个GUI中有很多轴的话,不指定对应的轴,那么GUI就不知道该在哪个轴上进行操作了。

轴的另一个用处是插入图片,代码为

axes(handles.xxx_axes)
image(imread('xxx.png'));
axis off;

第一行代码是指定对应的轴。

第二行代码是插入对应的图片。

第三行代码是取消轴的坐标轴显示。

这里我遇见了一个还没有解决的问题,就是在xxx_axes_CreateFcn()里写上面的代码的时候,再一次打开GUI的.fig文件,这个轴对应的tag就会消失不见,假如在其他控件下的Callback()里写上面的代码就不会出现这样的问题。

所以,可以用轴插入图片,给GUI做一个背景。先提前规划好GUI各个部分的用处,用PS做一个简单的背景,比如下面这样。

在这里插入图片描述
要比没有背景的GUI好看一些吧?可以花些巧思在绘制背景上,这样能够提升GUI的美观程度。

组(Group)

组,通常用来容纳其他的控件,可以把实现同一作用或实现同一对象功能的控件全部放在一个组里。在操作过程中,只需要对组进行操作即可。

在这里插入图片描述
组a.k.a.面板,长上面那个样子,一个对象一个组,多个对象多个组。这样可以提高效率,不必每个对象都再重新调整一遍控件,初始的组调好之后,后面的组只需要ctrl+c,ctrl+v即可。

进度条(Progress Bar)

进度条起一个提示作用,告诉用户现在算法进行到哪一步了,还有多久结束,让用户心里有数,不用着急。

进度条是一个很重要的控件!

没有进度条,用户都不知道算法的状况,可能等得不太耐烦了,把GUI关了。但是这样容易让电脑崩溃。

就连我们在生活里面做很多事情,假如没有进度条,也不知道这件事情到底在什么情况了,很容易放弃。

使用进度条的代码是:

h = waitbar(1,'算法仿真中......','name','目标跟踪仿真软件');

在这里插入图片描述
对上面的代码进行解释。

  • 1代表进度条被全部占满;
  • '算法仿真中......'代表进度条中间显示的文字;
  • name','目标跟踪仿真软件'代表进度条左上角显示的文字。

如果想让进度条显示百分比的话,可以用下面的代码:

h = waitbar(0,'算法仿真中......','name','目标跟踪仿真软件');
for i = 1:nt-1per_str = fix(i/nt*100);str = ['算法仿真中......',num2str(per_str),'%'];waitbar(i/nt,h,str);
end
close(h);

如果想简单一点,不用显示百分比,就让进度条动起来的话,用下面的代码:

h = waitbar(0,'算法仿真中......','name','目标跟踪仿真软件');
for i = 1:nt-1;waitbar(i/nt);
end
close(h);

close(h)代表关闭句柄为h的进度条,不然之后画图的时候会错画到进度条上,或者出现其他奇奇怪怪的错误。

GUI设计成品

好啦,该教的知识都已经教过了,下面开始实战吧!

下面这个GUI是添加了亿点点细节的成品,请看vcr。

在这里插入图片描述
源代码放在这里,大家按需取用,https:\luwin1127.github.io\assets\download\files-2024-01-22\MainGUI_Filter_Release_v1.0.zip。我的MATLAB是MATLAB 2018b版本,其他版本不保证能正常使用。

这个GUI实现的功能有:

  • 多种滤波方式的选择功能,包括:
    • 信息滤波;
    • UD滤波;
    • 遗忘滤波;
    • 自适应遗忘滤波。
  • 滤波器和目标状态参数输入功能。
  • 保存数据功能;
  • 保存仿真结果图功能;
  • 根据不同的滤波算法显示相应的滤波公式功能;
  • 进行仿真功能;
  • 退出软件功能。

保存数据功能可以实现带当天日期和不带当天日期两种格式,如下图所示。

在这里插入图片描述
这样就实现了不同滤波算法,不同时间下仿真的数据保存。

保存图片功能得到的图如下图所示。

在这里插入图片描述
按照不同滤波器和不同功能将仿真结果保存下来了。

将GUI所在的文件夹进行了适当美化,按照不同功能,将文件存于不同的文件夹,如下图所示。
在这里插入图片描述
这样不至于让用户打开GUI时看见文件夹很乱,干干净净的,比较美观,而且这样写代码也比较优雅。

最后

欢迎通过邮箱联系我:lordofdapanji@foxmail.com

来信请注明你的身份,否则恕不回信。


  1. 父对象,在我的理解中意思就是其他的控件都依存该对象存在,比如说有一个组,组里有两个按钮,那么该按钮显示位置就是在组里的坐标。组又依存于GUI之上,那么组的位置就是在GUI中的坐标。 ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/645155.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

12.前端--CSS-背景属性

1.背景颜色 样式名称: background-color 定义元素的背景颜色 使用方式: background-color:颜色值; 其他说明: 元素背景颜色默认值是 transparent(透明)      background-color:transparent; 代码演示: 背景色…

硬件基础:组合逻辑电路

什么是组合逻辑电路 组合逻辑电路是由一些基本的逻辑门电路组成的,没有反馈,输出仅取决于输入。 组合逻辑电路是数字逻辑电路中一种重要的电路类型,它是由多个逻辑门(例如与门、或门、非门等)组成的电路。组合逻辑电路…

APUE学习之信号(Signal)

目录 一、信号 1、基本概念 2、用户处理信号的方式 3、查看信号 4、可靠信号和不可靠信号 5、信号种类 6、终止进程信号的区别 二、进程对信号的处理 1、signal()函数 2、sigaction()函数 3、代码演示 4、运行结果…

k8s---HPA 命名空间资源限制

目录 HPA相关知识 HPA(Horizontal Pod Autoscaling)Pod 水平自动伸缩,Kubernetes 有一个 HPA 的资源,HPA 可以根据 CPU 利用率自动伸缩一个 Replication Controller、 Deployment 或者Replica Set 中的 Pod 数量。 (1…

LTD261次升级 | 小程序支持抖音客服、支持抖音登录 • 短信发送需实名认证 • 表单提交成功收邮件提醒

1、 抖音小程序新增抖音IM客服功能; 2、 抖音小程序支持一键登录、支持快捷授权手机号 3、 表单新增发送邮件到提交者邮箱; 4、 表单支持配置不自动推送客户管理; 5、 短信发送需实名认证签署承诺书; 6、 其他已知问题修复与优化&…

安装 nvm

前言: nvm 即 node 版本管理工具 (node version manager),好处是方便切换 node.js 版本。 通过将多个 node 版本安装在指定路径,然后通过 nvm 命令切换时,就会切换我们环境变量中 node 命令指定的实际执行的软件路径。 使用场景…

数据结构笔记1

来自《Python数据结构学习笔记》(张清云 编著) 第一章 数据结构基础 1.逻辑结构 集合:结构中的数据元素除了同属于一种类型外,别无其他关系线性结构:数据元素之间一对一的关系树形结构:数据元素之间一对…

抖音向微信引流主要有哪几种方法-数灵通

近年来,随着智能设备的普及和信息技术的进步,短视频制作门槛逐渐降低,用户自创视频数量迅猛增长,用户规模持续扩大,有力推动了移动短视频的繁荣发展,市场规模也在不断扩张。作为当下炙手可热的短视频APP&am…

pycharm安装过程

1、安装包官网下载 PyCharm: the Python IDE for Professional Developers by JetBrains 点击下载 下拉选择社区版本 选择下载 下载完成后,双击exe安装。 安装完成,生成的桌面快捷方式 同意并继续 进入开发界面

网络安全学习 --- 小实验

题目 要求 1.防火墙线下使用子接口分别对应两个内部区域。 2.所有分区设备可以ping通网关。 过程 1.接口,区域配置完成。 2.配置SWL2 vlan 2 vlan 3 # interface GigabitEthernet0/0/1port link-type trunkport trunk allow-pass vlan 2 to 3 # interface Giga…

JavaWeb之JavaScript-Vue --黑马笔记

什么是JavaScript? JavaScript(简称:JS) 是一门跨平台、面向对象的脚本语言。是用来控制网页行为的,它能使网页可交互。 JavaScript 和 Java 是完全不同的语言,不论是概念还是设计。但是基础语法类似。 …

java数据结构与算法刷题-----LeetCode667. 优美的排列 II

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 解题思路 题目要求我们返回一个数组长度为n的数组,必须含有1~n…

AI 欺诈事件频出,如何重塑身份认证的安全性?

据报告表示,生成式人工智能每年可为世界经济注入相当于 4.4 万亿美元的资金。预计到 2030 年,人工智能对全球财政的潜在贡献将达到 15.7 万亿美元。人们惊叹于 AI 强大工作效率,期待能帮忙节省不必要的劳动力,但事实上 AI 出现之后…

C++类的简单学习

C语言结构体中只能定义变量,在C中,结构体内不仅可以定义变量,也可以定义函数 之前在数据结构学习中,我们用C语言方式实现的栈,结构体中只能定义变量;现在以C方式实现,会发现struct中也可以定义函…

C++ Qt day1

提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数(要求使用C风格字符串完成) #include <iostream> #include <string.h> #include <array> using namespace std;int main() {string str;cout <<…

数据结构Java版(5)——链栈和链队列的实现

之前我们对链表进行了讲解&#xff0c;这次我们来用链表的方式来实现栈和队列两个接口&#xff0c;来加深我们对链表的理解。 一、链栈 栈的接口与顺序栈的接口相同&#xff0c;这里我们主要展示如何用我们自己写的链表来实现这个接口&#xff0c;代码展示如下&#xff1a; 接…

AI-数学-高中-8-函数奇偶性

原作者视频&#xff1a;函数】6函数奇偶性&#xff08;易-中档&#xff09;_哔哩哔哩_bilibili 示例&#xff1a; 已知奇偶性求解析式&#xff1a; 奇偶、单调函数综合示例&#xff1a;

黑马程序员——javase进阶——day01——匿名对象 , 继承 , 抽象类

目录&#xff1a; 面向对象回顾 面向对象的核心思想是什么?现有的类还是先有的对象?Java类的创建?类中的组成成分?创建对象所使用的关键字?创建对象的格式?调用对象的成员?定义构造方法的格式?定义构造方法的特点?构造方法的作用?面向对象三大特征是什么?封装的思想…

Java面试题:如何实现线程循环切换?

嗨大家好&#xff0c;我是小米&#xff01;今天我们要聊一个非常有趣的话题——社招面试题&#xff1a;Java中如何实现线程循环切换&#xff1f;大家都知道&#xff0c;在Java中处理多线程是一项非常常见而又重要的任务&#xff0c;而线程的循环切换更是其中的一大亮点。那么&a…

【图神经网络】GNNExplainer代码解读及其PyG实现

GNNExplainer代码解读及其PyG实现 使用GNNExplainerGNNExplainer源码速读前向传播损失函数 基于GNNExplainer图分类解释的PyG代码示例参考资料 接上一篇博客图神经网络的可解释性方法及GNNexplainer代码示例&#xff0c;我们这里简单分析GNNExplainer源码&#xff0c;并用PyTor…