• 嵌入式Qt-做一个秒表


    之前的文章:嵌入式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,然后可以修改字体的大小:

    再从左侧拖入其它需要用到的组件(PushButtonTextBrower)和位置调节组件(弹簧形状的HorizontalSpacerVericalSpacer

    进行水平布局和竖直布局,选中对应的组件,例如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"));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    超时时间到了之后,计算一些两次的时间差值,然后通过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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    主要是将时间归零,将显示情况,并将各个按钮的显示状态复位为默认显示状态。

    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]"));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    打点功能用于在秒表的运行过程中,记录不同名次的时间,并显示在右侧的文本显示框中。

    这里通过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
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    主要修改是将之前的小时显示去掉,并改为两个时间环:外圈秒环和内圈分环,秒环的范围是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
    
    • 1

    成功执行之后,就可以看到自动生成的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环境中测试运行情况。

  • 相关阅读:
    银行业数据治理的实施路径——基于资产管理的视角
    Java高级-代理(proxy)
    (178)Verilog HDL:设计一个计数器之exams/ece241_2014_q7a
    Godot 添加Nuget 引用
    C++day7
    【力扣白嫖日记】626.换座位
    Boomi入选《Inc.》杂志2022年5000家增速最快私营公司排行榜
    《机器学习实战》学习记录-ch3
    【一起学Rust】Rust学习前准备——注释和格式化输出
    用DIV+CSS技术设计的餐饮美食网页与实现制作(web前端网页制作课作业)HTML+CSS+JavaScript美食汇响应式美食菜谱网站模板
  • 原文地址:https://blog.csdn.net/hbsyaaa/article/details/126112372