当前位置:网站首页>嵌入式Qt-做一个秒表
嵌入式Qt-做一个秒表
2022-08-02 16:59:00 【码农爱学习】
之前的文章:嵌入式Qt-动手编写并运行自己的第1个ARM-Qt程序
介绍了如何编写第一个嵌入式Qt程序,实现了一个电子时钟的演示。
本篇,继续进行Qt实践,仿照手机中的秒表,实现一个相同功能的秒表:
回顾上一次的Qt开发流程,整个Qt的开发都是通过敲代码实现的,实际上,还可以利用Qt Creater的UI界面功能,通过图像化的配置来开发图形界面,本篇就使用这种方法来进行开发。
1 新建Qt工程
Qt工程创建的具体步骤可参照之前的文章:嵌入式Qt-动手编写并运行自己的第1个ARM-Qt程序,这里只说明不同之处。
上篇是通过代码实现页面设计的,本篇要借助Qt Creater的UI界面设计功能,因此要把下面的创建页面勾选上:
创建完成之后的Qt默认工程结构如下:
双击widget.ui,即可打开UI设置页面,如下图:
这里先简单熟悉下各个功能区:
2 代码编写
2.1 ui界面设计
修改界面的尺寸,我的Linux板子屏幕的分辨率是800x480,因此调整到对应的尺寸:
从左侧拖入一个Label,然后可以修改字体的大小:
再从左侧拖入其它需要用到的组件(PushButton、TextBrower)和位置调节组件(弹簧形状的HorizontalSpacer、VericalSpacer)
进行水平布局和竖直布局,选中对应的组件,例如3个按钮和中间的2个弹簧,点击上方工具栏中的水平布局按钮:
3个按键的水平布局效果如下:
然后再依次对其它组件进行布局:
字体可以调整到居中显示:
鼠标选中最大的组合组件,拖拽边缘调整到合适的外尺寸。然后选中不同级别的组合组件,调整layoutStretch的参数,实现按比例显示各个组件(相当于调节各个弹簧组件的弹力大小)
点击左下角上面那个三角图标,运行,查看效果:
注意左边留的空白是给秒表的表盘留的。
2.2 QTimer与QTime介绍
QTimer 类为定时器提供了一个高级编程接口,提供重复和单次计时。
QTime 类提供时钟时间功能,QTime 对象包含一个时钟时间,它可以表示为自午夜以来的小时数、分钟数、秒数和毫秒数。
Qt Creater提供了方便的帮助文档,可以在Qt Creater中直接查看对应功能函数的使用,比如搜索QTimer,就可以看到对应的介绍,以及可用的API函数:
本篇需要用到QTimer的功能有:
- start:启动定时器
- stop:停止定时器
再看看QTime的介绍:
本篇需要用到QTime的功能有:
- setHMS:设置初始时间
- addMSecs:增加一个时间(毫秒单位)
- toString:时间转为字符串格式
- minute:获取分钟
- second:获取秒
- msec:获取毫秒
2.3 对应按钮的函数
为了编写出更易看懂的代码,在编写代码之前,需要修改对应的组件的默认名称为便于理解的名称,比如我将3个按键的名称分别改为了:
- Btn_Start:开始按钮,并同时具有暂停/继续功能
- Btn_Reset:复位按钮
- Btn_Hit:打点按钮,用于记录不同名次的时间
然后还要手动添加QTimer和QTime对象,用于实现秒表的计时功能:
2.3.1 开始按钮的处理
Qt编程中重要处理就是信号和槽机制,它可用通过手动通过connet函数实现,而对于使用Qt Creater的图形界面设计方式,通常也是继续通过界面实现信号和和槽的连接:在开始按钮上右键,选则“转到槽…”:
然后有多种按钮信号可以选择,因为开始按钮同时具有暂停/继续的功能,这里使用toggled功能,利用按钮的按下和松开状态,来实现暂停/继续的功能:
点击OK之后,会自动跳到到代码页面,并自动生成对应的槽函数框架,然后就可以在里面编译对应的业务逻辑代码了:
开始按钮的具体业务逻辑代码如下,当首次按下时,checked为true,此时启动timer,记录此时的时间戳,然后将按钮的文字显示为“暂停”,同时将复位和打点按钮置灰,使这两个按钮不能再按下,因为暂停的时候执行复位和打点无意义。
timer每隔一段时间会触发超时,这里ADD_TIME_MSEC设置的是30ms,超时时间到后,编写对应的超时处理函数timeout_slot以及声明对应的信号和槽的处理。
void Widget::on_Btn_Start_toggled(bool checked)
{
if (checked)
{
timer.start(ADD_TIME_MSEC);
lastTime = QTime::currentTime();//记录时间戳
ui->Btn_Start->setText("暂停");
ui->Btn_Reset->setEnabled(false);
ui->Btn_Hit->setEnabled(true);
}
else
{
timer.stop();
ui->Btn_Start->setText("继续");
ui->Btn_Reset->setEnabled(true);
ui->Btn_Hit->setEnabled(false);
}
}
connect(&timer, SIGNAL(timeout()), this, SLOT(timeout_slot()));
void Widget::timeout_slot()
{
//qDebug("hello");
QTime nowTime = QTime::currentTime();
time = time.addMSecs(lastTime.msecsTo(nowTime));
lastTime = nowTime;
ui->Txt_ShowTime->setText(time.toString("mm:ss.zzz"));
}
超时时间到了之后,计算一些两次的时间差值,然后通过addMSecs函数来累加时间。
2.3.2 复位按钮的处理
复位按钮也是通过右键来调整到槽,注意这里使用clicked函数即可,因为复位按钮只需要使用它的点击按下功能:
对应的槽函数的具体实现如下:
void Widget::on_Btn_Reset_clicked()
{
m_iHitCnt = 0;
timer.stop();
time.setHMS(0,0,0,0);
ui->Txt_ShowTime->setText("00:00:00");
ui->Txt_ShowItem->clear();
ui->Btn_Start->setText("开始");
ui->Btn_Start->setChecked(false);
ui->Btn_Reset->setEnabled(false);
ui->Btn_Hit->setEnabled(false);
}
主要是将时间归零,将显示情况,并将各个按钮的显示状态复位为默认显示状态。
2.3.3 打点按钮的处理
打点按钮与复位按钮一样,也是只使用clicked函数即可,对应的槽函数的具体实现如下:
void Widget::on_Btn_Hit_clicked()
{
QString temp;
m_iHitCnt++;
temp.sprintf("--计次 %d--", m_iHitCnt);
ui->Txt_ShowItem->setFontPointSize(9);
ui->Txt_ShowItem->append(temp);
ui->Txt_ShowItem->setFontPointSize(12);
ui->Txt_ShowItem->append(time.toString("[mm:ss.zzz]"));
}
打点功能用于在秒表的运行过程中,记录不同名次的时间,并显示在右侧的文本显示框中。
这里通过setFontPointSize函数来设置不同大小的字体显示。
2.4 秒表表盘的实现
之前这篇文章:嵌入式Qt-动手编写并运行自己的第1个ARM-Qt程序,通过代码的方式,实现了一个时钟表盘的显示,本篇在这个的基础上,修改代码,实现一个显示秒和分的秒表表盘,具体修改后的代码如下:
connect(&timer, SIGNAL(timeout()), this, SLOT(update()));
connect(ui->Btn_Reset, SIGNAL(clicked()), this, SLOT(update()));
void Widget::paintEvent(QPaintEvent *event)
{
int side = qMin(width(), height());
//QTime time = QTime::currentTime();
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(width()/3, height()*2/5); //画图的基准位置
painter.scale(side/300.0, side/300.0); //随窗口尺寸自动缩放
//表盘(3个同心圆)
for (int i=0; i<PANEL_RADIUS_NUM; i++)
{
QBrush brush(stPanelParaArr[i].color);
QPen pen(stPanelParaArr[i].color);
painter.setBrush(brush);
painter.setPen(pen);
painter.drawEllipse(-stPanelParaArr[i].radius, -stPanelParaArr[i].radius, 2*stPanelParaArr[i].radius, 2*stPanelParaArr[i].radius);
}
//秒的刻度
painter.setPen(secondColor);
for (int i = 0; i < 60; i++)
{
if ((i % 5) == 0)
{
painter.drawLine(PANEL_RADIUS3-8, 0, PANEL_RADIUS3, 0);
QFont font("TimesNewRoman", SEC_NUM_SIZE);
painter.setFont(font);
painter.drawText(-SEC_NUM_SIZE, -(CLOCK_RADIUS-15), 2*SEC_NUM_SIZE, 2*SEC_NUM_SIZE, Qt::AlignHCenter, QString::number(i==0? 60 : i));
}
else
{
painter.drawLine(PANEL_RADIUS3-5, 0, PANEL_RADIUS3, 0);
}
//秒再细分5个格
for (int j = 0; j < 5; j++)
{
painter.rotate(6.0/5);
if (j != 4)
{
painter.drawLine(PANEL_RADIUS3-2, 0, PANEL_RADIUS3, 0);
}
}
}
//分钟的刻度
painter.setPen(minuteColor);
for (int k = 0; k < 30; k++)
{
if ((k % 5) == 0)
{
painter.rotate(-90.0);
painter.drawLine(PANEL_RADIUS4-8, 0, PANEL_RADIUS4, 0);
painter.rotate(90.0);
QFont font("TimesNewRoman", MIN_NUM_SIZE);
painter.setFont(font);
painter.drawText(-MIN_NUM_SIZE, -(PANEL_RADIUS4-10), 2*MIN_NUM_SIZE, 2*MIN_NUM_SIZE, Qt::AlignHCenter, QString::number(k==0? 30 : k));
}
else
{
painter.rotate(-90.0);
painter.drawLine(PANEL_RADIUS4-4, 0, PANEL_RADIUS4, 0);
painter.rotate(90.0);
}
painter.rotate(12.0);
}
//分钟的表针
painter.setPen(Qt::NoPen);
painter.setBrush(minuteColor);
painter.save();
painter.rotate(12.0 * (time.minute() + time.second() / 60.0));
painter.drawConvexPolygon(minuteHand, 3);
painter.restore();
//秒钟的表针
painter.setPen(Qt::NoPen);
painter.setBrush(secondColor);
painter.save();
//painter.rotate(6.0 * time.second());
painter.rotate(6.0 * (time.second()+time.msec()/1000.0));
painter.drawConvexPolygon(secondHand, 3);
painter.restore();
painter.end();
}
主要修改是将之前的小时显示去掉,并改为两个时间环:外圈秒环和内圈分环,秒环的范围是060秒,分环的范围是030分。
秒表表盘的显示效果如下:
3 编译运行
代码是在Window环境中的Qt Creater中编写的,首先是Windows中编译查看效果。
3.1 Windows中编译
在Windows中的运行效果如下图的右图,可以实现手机中秒表类似的计时效果:
3.2 Ubuntu中编译
将Windows中的QT工程源码:
- .cpp文件
- .h文件
- .pro文件
- .ui文件
复制到Ubuntu中,注意.user文件是不需要的(它是Windows平台的编译配置)。
然后使用ARM平台的编译工具链,我的是在”/home/xxpcb/myTest/imx6ull/otherlib/qt/qt-everywhere-src-5.12.9/arm-qt/“,这里需要先用到它的qmake工具先自动生成Makefile文件,再通过make指令进行编译。
使用qmake生成Makefile,进入程序源码目录,执行qmake指令:
/home/xxpcb/myTest/imx6ull/otherlib/qt/qt-everywhere-src-5.12.9/arm-qt/bin/qmake
成功执行之后,就可以看到自动生成的Makefile文件,然后执行make指令进行编译得到可执行文件。
3.3 Linux板子中运行
将可执行文件放到已配置了qt运行环境的Linux板子中,运行并查看效果:
https://www.bilibili.com/video/BV1XW4y1y7pK
注:
Ubuntu中的具体编译过程,可参考之前这篇文章:嵌入式Qt-动手编写并运行自己的第1个ARM-Qt程序
Ubuntu中Qt的交叉编译环境的配置,可参考之前这篇文章:嵌入式Linux-Qt环境搭建
4 总结
本篇通过一个秒表的实例,介绍了如何使用Qt Creator的UI界面设计功能,进行Qt的开发,并将代码进行交叉编译,放入i.MX6ULL的Linux环境中测试运行情况。
边栏推荐
猜你喜欢
随机推荐
golang源码分析(9)调度
关于我用iVX沉浸式体验了一把0代码项目创建
数字孪生园区场景中的坐标知识
再获权威认证!马上消费安逸花APP通过中国信通院“金融APP人脸识别安全能力评测”
golang刷leetcode动态规划(8)盈利计划
In the idea to create a web project _idea deployment of the web project
文件上传很难搞?10分钟带你学会阿里云OSS对象存储
什么是实时流引擎?
npm install 编译时报“Cannot read properties of null (reading ‘pickAlgorithm‘)“
navicat creates a connection 2002-can't connect to server on localhost (10061) and the mysql service has started the problem
【二】通过props进行传值,子页面多种方式接收
小程序实现手写左右翻页和动态修改横向滚动条位置
npm install报错Fix the upstream dependency conflict, or retry
Locking and Concurrency Control (4)
C语言中的一系列操作符
默认参数的代码实现及日期的注入与显示
H.265视频流媒体播放器EasyPlayer.js集成时报错“SourceBuffer ”如何解决?
Flink SQL builds real-time data warehouse DWD layer
一文搞懂│php 中的 DI 依赖注入
H5网页播放器EasyPlayer.js播放器界面的加载效果无法消失是什么原因?