自学内容网 自学内容网

QT----基于QML的计时器

赶上了实习的末班车,现在在做QML开发,第一天的学习成果,一个计时器.逻辑挺简单的,纯QML实现,代码在仓库QT-Timer
在这里插入图片描述

多线程优化

在使用的过程中发现自己的计时器时间会慢,并且一直点击记录的话时间1s可以走10s,排查发现是在计时器的间隔取得太小了,取了1太过于消耗资源,改成10的话能解决这个问题.同时也想尝试使用线程来解决.

新建TimerThread 类继承自QObject,只有这样才能使用线程.我们需要发送时间和运行的状态,因此使用信号和QML文件通信

#ifndef TIMERTHREAD_H
#define TIMERTHREAD_H

#include <QObject>
#include <QTimer>
#include <QThread>
#include <cmath>

/******************************************************************************
 *
 * @file       timerthread.h
 * @brief      把计时放入线程
 *
 * @author     纯真丁一郎
 * @date       2024/09/18
 * @Blog       https://www.relxdingyilang.cn/
 * @history
 *****************************************************************************/

class TimerThread : public QObject
{
    Q_OBJECT
public:
    explicit TimerThread(QObject *parent = nullptr);

    //判断运行状态
    bool isRunning = false;

    QString caculateTime(int totaltime);

signals:
    void timeUpdated(QString totaltimestr); //发送时间给主界面
    void sig_isRunning(bool isRunning);//发送状态

public slots:
    void start();
    void stop();
    void pause();
    void onTimeout();

private:
    int m_totaltime; //总时间
    QTimer *timer;
};

#endif // TIMERTHREAD_H

cpp里实现计时的功能启动计时器,计算时间格式.使用定时器的timeout信号,让我们的时间增加

#include "timerthread.h"

TimerThread::TimerThread(QObject *parent)
    : QObject{parent}
{
    m_totaltime = 0;
    timer = new QTimer(this);
    connect(timer,&QTimer::timeout,this,&TimerThread::onTimeout);

}

void TimerThread::start(){
    timer->start(1);
    isRunning = true;
    emit sig_isRunning(isRunning);
}

void TimerThread::pause(){
    timer->stop();
    isRunning = false;
    emit sig_isRunning(isRunning);
}

void TimerThread::stop(){
    timer->stop();
    isRunning = false;
    m_totaltime = 0;
    emit sig_isRunning(isRunning);
}

void TimerThread::onTimeout(){
    //计时
    m_totaltime += 1;
    emit timeUpdated(caculateTime(m_totaltime));
}

QString TimerThread::caculateTime(int totaltime){
    //格式化字符串
    int millisecond =totaltime % 1000;
    millisecond = std::floor(millisecond/10);
    int second = int(std::floor(totaltime /1000) )% 60;
    int minute = int(std::floor(totaltime/1000 /60)) % 60;

    QString result = (minute<10 ? "0":"") + QString::number(minute)+":"+
                     (second<10 ? "0":"") + QString::number(second) + ":"+
                     (millisecond<10 ? "0":"")+QString::number(millisecond);

    return result;
}

在main.cpp里实现多线程,实例化timerThread类,在实例化一个工作线程,把我们自己的类放入工作线程,启动工作线程即可.
同时我们需要qmlRegisterType来注册我们的类,这样才能让QML文件知道要与这个文件通信

 //注册计时线程,并将计时线程移动到工作线程
    TimerThread timerThread;
    QThread workerThread;
    timerThread.moveToThread(&workerThread);

    //启动工作线程
    workerThread.start();

    QQmlApplicationEngine engine;

    qmlRegisterType<TimerThread>("com.timerthread",1,0,"TimerThread");

main.qml的修改,首先使用import倒入我们的timerThread类,这样我们就可以在qml中实例化,可以加上idimport com.timerthread 1.0

定义两个变量,接受我们信号发送的参数.发送的参数的作用域只在Connection里,所以需要外部变量来接收,方便我们的使用,

 property bool isrunning: false
 property string totaltime: ""
 
 TimerThread{
        id:timerThread
    }
    Connections{
        target:timerThread
        // 使用传递过来的 totaltime 参数,信号传递出来的参数在connect内部可以直接使用,在外部不行
        onTimeUpdated:{
            timerDisplay.text = totaltimestr
            totaltime = totaltimestr
            //console.log(totaltime)
        }
        onSig_isRunning:{
            isrunning = isRunning
            console.log(isRunning)
        }
    }

后边就将原来的一些变量替换为新接收的变量就行.

使用多线程的方式,定时器间隔取1也能精确计时,线程起到了作用

点击访问博客查看更多内容

原文地址:https://blog.csdn.net/szn1316159505/article/details/142355017

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!