当前位置:网站首页>QT串口动态实时显示大量数据波形曲线(四)========“界面的美化与处理”
QT串口动态实时显示大量数据波形曲线(四)========“界面的美化与处理”
2022-07-30 05:45:00 【透明的光】
前言
做QT已经有一段时间了,从简单的串口通讯,到串口传输大量数据并显示,再到复杂的CAN通讯,再到更复杂的CAN传输大量数据并显示。逐渐认识到基本功能是很好实现的,并且需要的功能想想办法总能实现,但是看到别人做的QT界面才发现一个问题,别人做的很好看,并且看起来很实用。而自己做的仅仅是几个按钮加几个显示,并且总在一个界面或者几个界面中显示,感觉很不专业。所以通过各种方式获取到了高手都是怎么做的,下面一一详细叙说。
第一部分:主要心得
心得:
(1)一个QT工程,只有一个主界面,其他次界面都经过“点击”弹出,这样显得界面简洁。
(2)所有次界面的参数通过一定的方式传回主界面,主界面可以修改次界面的参数。
(3)输出的exe文件加入自己想要的图标,并且可以打包图标,使得自己最后能运行的文件只是一个自己设定图标的exe文件。
第二部分:主界面
准备工作:
(1)准备图片,准备好image文件夹,里面放入对应的png图片,这些能从QT的例子中找到,也能从网上下载到,反正越丰富越好。

(2)添加图片,这部分网上教程很多,这里就不介绍怎么在工程中添加文件了,添加之后是这个样子:

(3)添加action。这部分非常关键,关系到界面的美化程度和简洁性,还关系到后期加入次界面的问题。

至于怎么添加action,挺简单的,傻瓜式操作。这几个就是基本的按键,其实action就是以前咱们介绍的按钮,然后连接个槽函数就行了,点击图标之后,就能进入槽函数,或者弹出对应次界面了。
action添加好之后,必须拉到toolbar上,自己试着拉个试试,或者自己新建一个toolbar也可以,无所谓哪一个。之后就是程序了。
connect(m_ui->actionConnect, &QAction::triggered, this, &MainWindow::openSerialPort);
connect(m_ui->actionDisconnect, &QAction::triggered, this, &MainWindow::closeSerialPort);
connect(m_ui->actionSettion, &QAction::triggered, m_settings, &SerialSet::show);
connect(m_ui->actionHelp, &QAction::triggered, this, &MainWindow::help);
connect(m_ui->actionDownload, &QAction::triggered, this, &MainWindow::downloadSetData);
介绍:前面是action,也就是图标,后面就是槽函数。特别说明第三条:这个是次界面显示函数,点了之后就弹出次界面。这个后面还会介绍。

运行之后表头就成了这样,现在感觉专业点了吧!所以这个才是美化的效果。当然,现在还没看到专业的界面怎么做,自己也只能到这个程度了,只能将就着看了,自己感觉还不错。
这样主界面就完毕。
第三部分:次界面
这个是很头疼的事情,只能借鉴别人怎么编写的,前面已经介绍过怎么将其他界面的参数引入到主界面中,但是后来看到还是很头疼,看不懂了。所以搜寻了很多例程,最后确定一种可以很好利用的代码。下面只要介绍下次界面的添加和参数调用问题。
(1)添加次界面。这个应该挺好弄,在工程上右键,添加,ui文件,h文件,c文件。这个应该网上很多例程。这里就不介绍了。然后就是改写,这个挺重要,要不最后调用不了,就很麻烦,所以请小伙伴一步一步的看,一步一步的来,不能着急。
ui文件这个就不说了,这个随便拉,拉完就在.c文件里改变就行,这里也只控制他的界面形状,最重要的是参数传递。
以串口添加为例:

ui搞定后,这个是弹出界面,上节中已经有个qaction是show功能 ,点击齿轮按钮后,就会 弹出这个界面,选定参数后,点击确认,参数就会自动保存到一个变量里面,然后等待主界面去调用这个变量。
(2).h文件和.c文件
在串口的.h中,先定义串口文件的类:
QT_BEGIN_NAMESPACE
namespace Ui {
class SerialSet;
}
QT_END_NAMESPACE先建立主界面和次界面的连接:
在mainwindow的.h文件里,
SerialSet *m_settings = nullptr;在mainwindow的.c文件开头,调用定义好的类。
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, m_ui(new Ui::MainWindow)
, m_settings(new SerialSet)
{
m_ui->setupUi(this);
}然后利用前面的qaction就可以show串口的ui界面了。
connect(m_ui->actionSettion, &QAction::triggered, m_settings, &SerialSet::show);至于为啥这样写,我也不知道,反正是能用,点击齿轮按钮,这个ui界面就弹出来了。
当然删除ui的时候都得删除:
MainWindow::~MainWindow()
{
delete m_settings;
delete m_ui;
}这个代码直接在mainwindow.c里面添加就好,有现成的地方,直接复制粘贴过去就好。
下面就是最关键的一步,参数传递。
在串口.h文件中:
class SerialSet : public QWidget
{
Q_OBJECT
public:
explicit SerialSet(QWidget *parent = nullptr);
~SerialSet();
public:
struct Settings {
QString name;
qint32 baudRate;
QString stringBaudRate;
QSerialPort::DataBits dataBits;
QString stringDataBits;
QSerialPort::Parity parity;
QString stringParity;
QSerialPort::StopBits stopBits;
QString stringStopBits;
};
Settings settings() const;
private:
Settings m_currentSettings;
private:
Ui::SerialSet *m_ui = nullptr;
};逐个解释下:先定义结构体,里面是ui对应的参数,也就是串口波特率,校验位啥的,最好用结构体,当然不用也行,这个是线程的模板,方便又实惠。
然后定义函数和变量,也就是setting()和m_currentsettings ,为啥这样定义,不知道,也就是一个是调用的函数,一个是变量。
这个函数的程序在串口.c里面:
SerialSet::Settings SerialSet::settings() const
{
return m_currentSettings;
}也就是执行这个函数的时候,返回定义m_currentsettings 的值,也就是结构体各个参数的值。
m_currentSettings.name = m_ui->serialPortInfoListBox->currentText();
m_currentSettings.baudRate = static_cast<QSerialPort::BaudRate>(m_ui->baudRateBox->itemData(m_ui->baudRateBox>currentIndex()).toInt());
m_currentSettings.stringBaudRate = QString::number(m_currentSettings.baudRate);
而m_currentsettings 的各个结构体变量的值直接通过串口的ui给取过来。
准备好后,就可以在mainwindow中调用了。
const SerialSet::Settings p = m_settings->settings();
m_serial->setPortName(p.name);
m_serial->setBaudRate(p.baudRate);
m_serial->setDataBits(p.dataBits);
m_serial->setParity(p.parity);
m_serial->setStopBits(p.stopBits);定义setting指针p,指向串口类中的setting()函数。这样就将串口.ui的值传到了主界面里。
说到这里应该感觉到有点绕。下面梳理一下:
第一步:定义一个结构体Settings,里面包含串口ui需要传递的参数;
第二步:定义一个结构体变量m_currentsettings,将串口ui界面的参数,放到这个变量里(因为是结构体,直接m_currentsettings.变量就行了)。
第三步:定义结构体函数setting(),准备在主函数中执行。并且函数的内容是return结构体变量m_currentsettings。
注意:这点有点不明白,为啥还得定义一个以结构体开头的函数,可能是函数和参数必须相同类型才行,这点先不考虑了,弄不明白。
第四步:主函数中定义次函数的函数m_settings,并放入程序开头,也就是主函数包含次函数。
第五步:定义指针p 等于m_settings的setting函数。这样这个函数返回来其中的结构体数据,然后直接幅值给主函数中的参数了。
当然直接定义变量也是可以在主界面中直接用的,不过需要加上m_settings才行,应为这个才是最大的框框,必须有这个,才能找到里面的变量。
(3)运行界面

点击确认后,关闭界面,就将串口参数传递到结构体中了,然后在主界面,连接串口中,再将结构体的参数传递给真正的串口设置,就可以了。
第四部分:结论
美观是第一要务,功能排第二。差不多就是个参数传递,想试试的小伙伴可以一步一步来,如果不行的话,需要源码的话,关注下面公众号,源码程序会放在消息中,关注后直接搜索历史消息就能看到。

边栏推荐
- Rsync realizes folder or data synchronization between Win systems
- 原创 Acegi 1.03 安全机制
- Kaggle-M5
- Jdbc & Mysql timeout analysis
- Trust anchor for certification path not found. Exception solution.
- 思谋面试准备
- MySQL data types and footprint
- 常用损失函数(一):Focal Loss
- Atmospheric particulate matter PMF source analysis
- Flood Control Assessment Report Compilation Method and Flood Modelling under the New Guidelines (HEC-RAS)
猜你喜欢

十三、Kotlin进阶学习:内联函数let、also、with、run、apply的用法。

Knowledge distillation method of target detection

nodejs PM2监控及报警邮件发送(二)

AAcell五号文档室——跨平台文件传输的小室一间一间的

常用损失函数(一):Focal Loss

九、Kotlin基础学习:1、Companion的扩展方法和扩展属性;2、一般类的扩展方法和扩展属性;3、委托;

MySQL 数据类型及占用空间

Trust anchor for certification path not found.异常解决方法。

Dropout原理及作用

Jdbc & Mysql timeout analysis
随机推荐
生产力工具分享——简洁而不简单
基于遥感解译与GIS技术环境影响评价图件制作(最新导则)
Self-augmented Unpaired Image Dehazing via Density and Depth Decomposition程序运行记录
Redis 客户端常见异常分析
HSPF 模型应用
十、Kotlin基础学习:1、延迟加载;2、异常处理;3、使用 throw 主动抛出异常;4、自定义异常;
nodejs PM2监控及报警邮件发送(二)
边境的悍匪—机器学习实战:第四章 训练模型
shardingsphere 分库分表及配置示例
十三、Kotlin进阶学习:内联函数let、also、with、run、apply的用法。
Rsync实现Win系统间的文件夹或数据同步
Pytorch(三):可视化工具(Tensorboard、Visdom)
MySQL data types and footprint
卷积神经网络(CNN)之卷积操作、池化操作、激活函数
mysql delete duplicate data in the table, (retain only one row)
Mysql 客户端常见异常分析
海量遥感数据处理与GEE云计算技术应用【基础、进阶】
大气颗粒物 PMF 源解析
DeepLearing4j's deep learning Yolo Tiny realizes target detection
对于国内数据交换平台的分析