流程:
工程目录:
mythread.h:
#ifndef MYTHREAD_H #define MYTHREAD_H #include <QObject> class MyThread : public QObject { Q_OBJECT //要使用信号和槽必须有的宏, public: explicit MyThread(QObject *parent = 0); //线程处理函数 void myTimerout(); //由于bool isStop是私有的,需要定义一个公有接口,这里使用的是默认参数 void setFlag(bool flag = true); signals: void mySignal(); public slots: private: bool isStop; }; #endif // MYTHREAD_H
mywidget.h:
#ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> #include "mythread.h" #include <QThread>//添加在这里作为全局 namespace Ui { class MyWidget; } class MyWidget : public QWidget { Q_OBJECT public: explicit MyWidget(QWidget *parent = 0); ~MyWidget(); void dealSignal(); void dealclose();//点击叉号槽函数 signals: void startThread();//启动子线程的信号 private slots: void on_buttonStart_clicked(); void on_buttonStop_clicked(); private: Ui::MyWidget *ui; MyThread *myT; QThread *thread; }; #endif // MYWIDGET_H
mythread.cpp:
#include "mythread.h" #include <QThread>//待会用到sleep函数 #include <QDebug> MyThread::MyThread(QObject *parent) : QObject(parent) { isStop = false; } void MyThread::myTimerout() { // while(1) // { // //每隔一秒发射一次mySignal(), // QThread::sleep(1); // emit mySignal(); // qDebug()<<"子线程号: "<<QThread::currentThread(); // } //换成如下代码 while(isStop == false) { //每隔一秒发射一次mySignal(), QThread::sleep(1); emit mySignal(); qDebug()<<"子线程号: "<<QThread::currentThread(); if (true == isStop) { break; } } } void MyThread::setFlag(bool flag) { isStop = flag; }
mywidget.cpp:
#include "mywidget.h" #include "ui_mywidget.h" #include <QDebug> MyWidget::MyWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MyWidget) { ui->setupUi(this); //动态分配空间, 不能指定父对象,由于没有指定父对象,所以我们需要手动将其delete掉 myT = new MyThread; //创建子线程 thread =new QThread(this); //把自定义的线程加入到子线程中 myT->moveToThread(thread); connect(myT,&MyThread::mySignal,this,&MyWidget::dealSignal); qDebug()<<"主线程号: "<<QThread::currentThread(); connect(this,&MyWidget::startThread,myT,&MyThread::myTimerout);//只能通过signal - slot 方式调用 connect(this,&MyWidget::destroyed,this,&MyWidget::dealclose); //线程处理函数内部,不允许操作图形界面 //面试题:connect()第五个参数的作用,第五个参数是:连接方式:默认,队列,直接 //多线程时才有意义 //默认的时候, //如果是多线程,默认使用队列 //如果是单线程,默认使用直接方式 //队列:槽函数所在的线程和接收者一样 //直接:槽函数所在线程和发送者一样 } MyWidget::~MyWidget() { delete ui; } void MyWidget::dealclose() { on_buttonStop_clicked(); delete myT; } void MyWidget::dealSignal() { static int i = 0; i++; ui->lcdNumber->display(i); } void MyWidget::on_buttonStart_clicked() { if (thread->isRunning() == true) { return; } //启动线程,但是没有启动线程处理函数 thread->start(); myT->setFlag(false ); //不能直接调用线程处理函数 //直接调用(即myT->myTimerout();),导致线程处理函数和主线程是在同一个线程 //只能通过signal - slot 方式调用 emit startThread(); } void MyWidget::on_buttonStop_clicked() { //在这里由于使用的是while(1),其实线程是不能退出的,这是因为quit()要等线程走完再退出,但是while(1)是死循环,走不完。 //所以我们应该在while函数下功夫,即设置一个标志位, if(thread->isRunning() == false) { return; } myT->setFlag(true); thread->quit(); thread->wait(); }
ui:
转载于:https://www.cnblogs.com/doker/p/11162523.html