cpluspluser

电脑杂谈  发布时间:2020-06-30 06:23:42  来源:网络整理

qt terminate线程_qt 线程传递参数_qt多线程绘图

Qt提供对线程的支持. 它提供了一些与平台无关的线程类. 要执行多线程方法,有两种方法.

Qt提供了QThread类. QThread类中有一个虚函数QThread :: run().

要创建一个新线程,我们只需要定义一个MyThread类,让它继承QThread,然后重新实现QThread :: run().

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
    ~MyThread();
protected:
    //QThread的虚函数
    //线程处理函数
    //不能直接调用,通过start()间接调用
    void run();
signals:
    void isDone();  //处理完成信号
signals:
public slots:
};
#endif // MYTHREAD_H
};

然后您可以编写要在运行中执行的操作,例如,可以等待5秒钟. 如果不是多线程qt多线程绘图qt多线程绘图,则在运行时单击窗口,窗口将显示为无响应.

那么您如何告诉线程结束?这可以使用qt的信号和时隙机制. 操作完成后,我们可以发出完成信号. 完成信号在声明文件中定义.

void MyThread::run()
{
    //很复杂的数据处理
    //需要耗时5秒
    sleep(5);
    emit isDone();  //发送完成信号
}

通过这种方式,我们已经完成了线程操作的编写.

现在,让我们首先布置一个简单的ui,仅使用一个LcdNumber和一个PushButton.

qt多线程绘图_qt 线程传递参数_qt terminate线程

在当前窗口小部件头文件中定义一些必需的操作. 并加入我们定义的线程文件.

#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include <QTimer>
#include "mythread.h"  //线程头文件
namespace Ui {
class MyWidget;
}
class MyWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();
    void dealTimeout();  //定时器槽函数
    void dealDone();   //线程槽函数
    void stopThread();  //停止线程
private slots:
    void on_pushButton_clicked();
private:
    Ui::MyWidget *ui;
    QTimer *myTimer;  //声明变量
    MyThread *thread;  //线程对象
};
#endif // MYWIDGET_H

我们使用计时器让Lcd控件根据指定的时间更新数字. 当我们单击开始按钮时,计时器启动,并自动触发超时信号. 要捕获超时信号,请在DealTimerout()函数中写入所需的操作. 捕获超时后,将自动使用dealTimerout插槽功能.

dealTimerout()我们可以这样写:


void MyWidget::dealTimeout()
{
    static int i = 0;
    i++;
    //设置lcd的值
    ui->lcdNumber->display(i);
}

在小部件构造函数中,首先创建一个计时器并为线程函数分配空间:

myTimer = new QTimer(this);
thread = new QThread(thread);  //分配空间

然后我们将信号和插槽关联起来:

//只要定时器启动,自动触发timeout
connect(myTimer, &QTimer::timeout, this, &MyWidget::dealTimeout);

qt 线程传递参数_qt多线程绘图_qt terminate线程

在开始按钮的插槽功能中,启动计时器并启动线程. 需要注意的是,我们不能直接调用run函数,而可以通过start()间接调用线程函数.

void MyWidget::on_pushButton_clicked()
{
    //若定时器没有工作
    if(myTimer->isActive() == false)
    {
        myTimer->start(100);
    }
    //启动线程,处理数据
    thread->start();
}

程结束时,我们收到了isDone信号,在此我们关闭了计时器:

void MyWidget::dealDone()
{
    qDebug() << "it is over";  //打印线程结束信息
    myTimer->stop();  //关闭定时器
}

我们选择退出窗口时关闭线程. 退出窗口时将触发被破坏的信号. 线程关闭的插槽功能实现如下:

void MyWidget::stopThread()
{
    //停止线程
    thread->quit();
    //等待线程处理完手头工作
    thread->wait();
}

最后,在小部件主窗口的构造函数中添加线程的关联信号和插槽:

connect(thread, &MyThread::isDone, this, &MyWidget::dealDone);
//当按窗口右上角x时,触发destroyed信号
connect(this, &MyWidget::destroyed, this, &MyWidget::stopThread);

现在,当我们启动程序时,窗口如下:

qt terminate线程_qt 线程传递参数_qt多线程绘图

当我们单击“开始”按钮时,将触发计时器,启动线程,并且Lcd中的值每100ms更新一次:

5秒后,线程停止,发出isDone信号,执行DealDone插槽功能,显示其结束并关闭计时器:

再次单击,再次启动计时器,继续累积数字并将其设置为Lcd,单击x,程序退出并停止线程.

创建一个新项目,ui如图所示:

创建一个继承自QObject的新类,然后在该类中设置一个线程函数.

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
class MyThread : public QObject
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
    ~MyThread();
    //线程处理函数
    void MyTimeout();
    void setFlag(bool flag = true);
signals:
    void mySignal();
public slots:
private:
    bool isStop;
};
#endif // MYTHREAD_H

通过bool变量控制线程的末尾,并通过发出mySignal()信号来调用处理插槽函数.

qt多线程绘图_qt terminate线程_qt 线程传递参数

在小部件中定义如下:

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "mythread.h"
#include <QThread>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    void dealSignal();
    void dealClose();
signals:
    void startThread();  //启动子线程的信号
private slots:
    void on_pushButtonStart_clicked();
    void on_pushButtonStop_clicked();
private:
    Ui::Widget *ui;
    MyThread *myT;
    QThread *thread;
};
#endif // WIDGET_H

两个插槽函数dealSignal()和dealClose()分别与mySignal()和destroy()信号关联.

信号startThread()用于启动子线程.

在小部件的实现中,

各种功能的实现如下:

void Widget::dealSignal()
{
    static int i = 0;
    i++;
    ui->lcdNumber->display(i);
}
//Start按钮
void Widget::on_pushButtonStart_clicked()
{
    if(thread->isRunning() == true)
    {
        return;
    }
    //启动线程,但是没有启动线程处理函数
    thread->start();
    myT->setFlag(false);
    //不能直接调用线程处理函数,直接调用导致线程处理函数和主线程在同一个线程
    //myT->MyTimeout();
    //只能通过 signal - slot方式
    emit startThread();
}
//Stop按钮
void Widget::on_pushButtonStop_clicked()
{
    if(thread->isRunning() == false)
    {
        return;
    }
    myT->setFlag(true);
    thread->quit();
    thread->wait();
}
void Widget::dealClose()
{
    on_pushButtonStop_clicked();
    delete myT;
}

在DealSignal中,增加Lcd号.

按下“开始”按钮时,将启动线程,将线程标志设置为flase,并通过发出startThread()信号来调用真实的线程函数MyThread :: MyTimeout.

按下“停止”按钮时,将线程标志设置为true并关闭线程.

由于未为myT指定父对象,因此我们需要手动释放内存. 单击x时,线程将关闭并删除.

运行如下所示:


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-263237-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...