QT中QThread, QTimer的使用(完整代码)

************************************************************
author: hjjdebug
date:   2024年 02月 03日 星期六 11:23:29 CST
description: QT中QThread, QTimer的使用
目的: 用最简单的程序
1. 了解QT编程的框架
2. 了解QThread 对象的使用
3. 了解QTimer 对象的使用
************************************************************

要求1. 实现一个程序,每1秒钟打印一个数,从1打印到9.
----------------------------------------
1. 非qt的程序, 
----------------------------------------

#include <stdio.h>
int main()
{
 for(int i=i;i<10;i++)
 {
     printf("data is %d\n",i);
    sleep(1);
 }
 return 0;
 }

----------------------------------------
 2. qt程序的实现。
----------------------------------------
 2.1: 首先, qt程序是有一个框架的,它的主流程是这样的。
 int main(int argc,char *argv[])
 {
   QApplication *app=new QApplication(argc,argv);
   ....
   return app->exec();
}
 你的while循环或者for 循环不能放到主线程中,只能放到其它线程中
 因为主线程是负责消息分发的.
 下面看看把一个for 循环或while循环放到一个线程中的解决方法。

------------------------------------------------------------
 2.2: 把循环用传统的c调用接口 pthread_create 创建线程来实现
------------------------------------------------------------
 以下程序均编译通过.
#include <QApplication>
#include <unistd.h>
void *thread_routine(void *)
{
    for(int i=1;i<10;i++)
    {
        printf("data is %d\n",i);
        sleep(1);
    }
    return 0;
}
int main(int argc,char *argv[])
{
    QApplication *app=new QApplication(argc,argv);
    pthread_t threadid;
    pthread_create(&threadid,NULL,thread_routine,NULL);
    printf("threadid:%ld\n",threadid);
    return app->exec();
}
运行结果:
./test_thread_qt 
threadid:139793910314752
data is 1
data is 2
data is 3
data is 4
data is 5
data is 6
data is 7
data is 8
data is 9
用pthread_create 来创建线程很简洁,挺好的.
但QT又自己实现了一套机制,用Qt的QTread 显得更本土化,它是c++接口,面向对象的,如下:

----------------------------------------
2.3 把循环用QThread线程来实现
----------------------------------------
#include <QApplication>
#include <unistd.h>
#include <QThread>
class CMyThread : public QThread
{
    public:
        CMyThread(){}
        ~CMyThread(){}
        void run(void ) override   // 重写run 函数
        {
            pthread_t threadid=gettid();
            printf("sub threadid:%ld\n",threadid);
            for(int i=1;i<10;i++)
            {
                printf("data is %d\n",i);
                sleep(1);
            }
        }
};
int main(int argc,char *argv[])
{
    QApplication *app=new QApplication(argc,argv);
    CMyThread *myThread = new CMyThread();  //创建了一个QThread 对象,这个对象是QThread的继承类
    myThread->start();
    pthread_t threadid=gettid();
    printf("main threadid:%ld\n",threadid);
    return app->exec();
}

编程架构说明:
1. 主线程中,创建一个CMyThread 对象,继承自QThread, 它复写了QThreadd 的run 函数.
   面向对象的编程方法.
   然后调用对象的start()
   即可实现子进程的运行
   然后你要完善生成对象的类。

下面是执行结果:
./test_thread_qt 
main threadid:5583
sub threadid:5589
data is 1
data is 2
data is 3
data is 4
data is 5
data is 6
data is 7
data is 8
data is 9

----------------------------------------
2.4: 把sleep() 函数用QTimer 来实现.
----------------------------------------
sleep 调用就是最简单的,为什么要用QTimer?
是的,这里是为了演示QTimer 的用法,看一看如何用一个复杂的架构来实现.
因为当一个任务很复杂时,必须要拆分为更精细的部分加以控制.
创建一个QTimer 对象,1秒钟定时,时间到会回调用户程序,完成i加法和打印

用了QTimer, 就不用QThread 对象了, 因为QTimer的回调就在一个线程中.
但是根据c++的面向对象的编程方法,我们还是要创建一个对象,QT中能够使用消息
的对象都是继承自QObject, 这里的实现是创建了一个CMyObject 类,该类包含一个QTimer对象
下面是完整代码, 主线程中还是创建object,然后再启动timer就可以了
主函数main.cpp 还是那么简单. 
$ cat main.cpp
#include <QApplication>
#include "myObject.h"
int main(int argc,char *argv[])
{
    QApplication *app=new QApplication(argc,argv);
    CMyObject *myObj = new CMyObject();  // Qt中的对象都是QObject的子对象
    myObj->start();
    pthread_t threadid=gettid();
    printf("main threadid:%ld\n",threadid);
    return app->exec();
}
myObject.h 必须要分开独立写了,因为它包含了Q_OBJECT 宏, 该宏是收发消息所必须的,
有了该宏,QT 就会调用moc 工具从 myObject.h 生成moc_myObject.cpp
如果把它放到main.cpp中而不单独拉出一个.h头文件,就无法生成moc_*.cpp 文件,最后会有连接错误,
如下:
 undefined reference to `vtable for CMyObject'

 下面附上完整的myObject.h 和myObject.cpp 代码

$ cat myObject.h
#include <QObject>
#include <QTimer>
#include <unistd.h>
class CMyObject : public QObject
{
    Q_OBJECT
    public:
        CMyObject(QObject *parent=nullptr) : QObject(parent)
        {
            m_timer = new QTimer();
            connect(m_timer,SIGNAL(timeout()),this,SLOT(slotTimeout()));
        }
        ~CMyObject(){}
        void start()
        {
            m_timer->start(1000); //启动timer,1秒时间到
        }
    private slots:
        void slotTimeout(void )  //时间到后的槽函数
        {
            pthread_t threadid=gettid();
            printf("sub threadid:%ld\n",threadid); //发现timerID 与主线程ID 是一样的,就是同一个线程
            m_i++;
            printf("data is %d\n",m_i);
            if(m_i==9)  // 何时退出循环,清理现场,需要判断
            {
                disconnect(m_timer,SIGNAL(timeout()),this,SLOT(slotTimeout()));
                delete m_timer;
                m_timer=NULL;
            }
        }
    private:
        QTimer *m_timer;        // 该类中包含了一个QTimer 对象
        int m_i=0;
};
$ cat myObject.cpp
#include "myObject.h"

下面是其执行结果:
$ ./test_qtimer 
main threadid:8374
sub threadid:8374
data is 1
sub threadid:8374
data is 2
sub threadid:8374
data is 3
sub threadid:8374
data is 4
sub threadid:8374
data is 5
sub threadid:8374
data is 6
sub threadid:8374
data is 7
sub threadid:8374
data is 8
sub threadid:8374
data is 9
可见timer slot 函数线程ID 就是主线程ID
 

  • 14
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值