Qt中子线程调用定时器实例

37 篇文章 18 订阅
36 篇文章 13 订阅

前言
一、不指定父对象实例化线程和定时器变量
二、线程间通过信号和槽的方式传数据
总结
前言
Qt作为人机交互界面开发的主流工具,在工业控制领域也得到了广泛的应用。工业控制中,需要对大量的实时数据读取、显示、计算和保存,在一个线程中实现这些功能,很有可能会造成界面卡死的情况。本文介绍一种不需要重写子线程类的简单方法使用定时器。

一、不指定父对象实例化线程和定时器变量
1.在头文件中声明定时器指针变量和线程指针变量;
2.在构造函数中实例化时不指定父对象;
3.将定时器通过moveToThread的方式转移到子线程中;
4.将线程开启的信号和定时器开启的槽函数相连;
5.将定时器和对应的槽函数相连;
6.注意:连接定时器和槽函数时,不能使用默认的连接方式,应使用Qt::DirectConnection直接连接的方式。直接连接表示槽函数和信号发出者处于同一个线程中,只有这样才可以完成在子线程中使用定时器的槽函数;
7.PS:Connect第5个参数为默认的队列方式,是为不同线程设计的。

代码如下:

    timer0 = new QTimer;//动态分配内存的方法,不指定父对象
    timer0Thread0 = new QThread;//动态分配内存,不指定父对象
    timer0->setTimerType(Qt::PreciseTimer);//设置精确的定时器
    timer0->setInterval(1000);//每隔1秒触发一次定时器

    timer0->moveToThread(timer0Thread0); //将定时器转移到子线程中
    connect(timer0Thread0,SIGNAL(started()),timer0,SLOT(start()));//线程打开同时启动线程中的定时器
    connect(timer0,SIGNAL(timeout()),this,SLOT(timer0outSlot()),Qt::DirectConnection);//子线程给主线程发信号

二、线程间通过信号和槽的方式传数据
1.通过带形参的信号和槽完成线程间的信息传递;
2.注意:在构造函数中信号和槽函数的括号中不能写实参,只写变量类型就好,否则会报错。

代码如下:

connect(this,SIGNAL(SendData(const QString)),this,SLOT(ReceiveDataAndShow(const QString)));//通过信号和槽的方式从子线程向主线程传数据
1
1.cpp程序中完成程序如下:

代码如下:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    timer0 = new QTimer;//动态分配内存的方法,不指定父对象
    timer0Thread0 = new QThread;//动态分配内存,不指定父对象
    timer0->setTimerType(Qt::PreciseTimer);//设置精确的定时器
    timer0->setInterval(1000);//每隔1秒触发一次定时器

    timer0->moveToThread(timer0Thread0); //将定时器转移到子线程中
    connect(timer0Thread0,SIGNAL(started()),timer0,SLOT(start()));//线程打开同时启动线程中的定时器
    connect(timer0,SIGNAL(timeout()),this,SLOT(timer0outSlot()),Qt::DirectConnection);//子线程给主线程发信号
    connect(timer0Thread0,SIGNAL(finished()),timer0,SLOT(stop()));//关闭线程的同时关闭定时器
    connect(this,SIGNAL(SendData(const QString)),this,SLOT(ReceiveDataAndShow(const QString)));//通过信号和槽的方式从子线程向主线程传数据
}

Widget::~Widget()
{
    if(timer0Thread0->isRunning())
    {
        timer0Thread0->quit();
        timer0Thread0->wait();
    }
    delete timer0;
    delete timer0Thread0;
    delete ui;

}
void Widget::timer0outSlot()
{
    int id = (int) QThread::currentThreadId();
    static int cnt = 0;
    cnt = (cnt <= 100)? ++cnt : 1;
    i = i + 100;

    QString str = "Slot_Thread_id:" + QString::number(id) + " secondNum " + QString::number(i);
    //ui->textBrowser->append(str);//可以直接用这种方法更改主线程界面的值
    //但会报一个警告“QObject::connect: Cannot queue arguments of type 'QTextCursor'
    //(Make sure 'QTextCursor' is registered using qRegisterMetaType().)”
    //更好的方法是通过发送信号的方式
    emit SendData(str);
    str.clear();
    str = "number: " + QString::number(cnt);
    //ui->textBrowser->append(str);
    emit SendData(str);
}


void Widget::on_pushButtonStart_clicked()
{
    int id = (int)QThread::currentThreadId();
    QString str = "GUI_Thread_ID: " + QString::number(id);
    //ui->textBrowser->append(str);
    emit SendData(str);
    if(!timer0Thread0->isRunning())
    {
        timer0Thread0->start();
    }
}

void Widget::on_pushButtonStop_clicked()
{
    int id = (int)QThread::currentThreadId();
    QString str = "GUI_Thread_ID: " + QString::number(id);
    //ui->textBrowser->append(str);
    emit SendData(str);
    if(timer0Thread0->isRunning())
    {
        timer0Thread0->quit();
        timer0Thread0->wait();
    }
}

void Widget::on_pushButtonClear_clicked()
{
    ui->textBrowser->clear();
}
void Widget::ReceiveDataAndShow(const QString &text)
{
    ui->textBrowser->append(text);
}

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值