在gui編程里,一個子函數的運行時間可能過長,界面就處於假死狀態,原因是窗口是一個線程,子函數也在這個線程里,一些事件也要在這個線程里處理。
如果子函數運行時間過長,系統沒有辦法調用事件監聽循環,gui就處於假死。一般有兩種辦法:
子函數事件不是很長,可以在子函數中間插入一些 QCoreApplication::processEvents
另一種方法就是把耗時的工作放到另一個線程里,通過信號槽來傳遞。這里介紹Qobject的moveToThread方法。
下面使用老板和員工的例子來講,有兩個BT老板,閑的蛋疼,安了個鬧鍾,每個一段時間查員工的崗。
代碼如下:
#include <QCoreApplication> #include <QThread> #include <QTimer> #include <QObject> #include <QDebug> #include "worker.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qDebug()<<"main thread is :"<<QThread::currentThreadId()<<endl; //打印主線程的線程號
QTimer *boss1 = new QTimer(); boss1->setInterval(5000); QThread *t1=new QThread(); //來一個新的線程 t1->start(); //啟動線程 Worker w1("Bob"); //創建一個對象 w1.moveToThread(t1); //把這個對象移到線程t1里 QObject::connect(boss1, SIGNAL(timeout()), &w1, SLOT(run())); //通過信號槽機制將boss1和worker1連接起來,每個一段時間查一次看看員工工作沒 QTimer *boss2 =new QTimer();
boss2->setInterval(3000); QThread *t2=new QThread(); //來一個新的線程 t2->start(); //啟動線程 Worker w2("Stuart"); //創建一個對象 w2.moveToThread(t2); //把這個對象移到線程t2里 QObject::connect(boss2, SIGNAL(timeout()), &w2, SLOT(run())); boss1->start(); boss2->start(); return a.exec(); }
worker類
注意的是worker類一定要繼承Qobject
#ifndef WORKER_H #define WORKER_H #include <QObject> #include <iostream> class Worker : public QObject { Q_OBJECT public: explicit Worker(QString name, QObject *parent = nullptr); long runnum=0; QString name; signals: public slots: void run(void); }; #endif // WORKER_H
#include "worker.h" #include <QDebug> #include <QThread> Worker::Worker(QString name ,QObject *parent) : name(name),QObject(parent) { qDebug()<<"Hi, I'm worker:"<<name<<" at thread number:"<<QThread::currentThreadId()<<endl; } void Worker::run() { runnum++; qDebug()<<"I'm "<<name<<" don't spy me so frequently boss! I'm busy in my work.........."; qDebug()<<"you have spy me "<<runnum<<" times!"<< "I'm working at thread num :"<<QThread::currentThreadId()<<endl; long s=1000; for (long i=0; i<s;i++){ } }
運行后的結果:
main thread is : 0x6be0 Hi, I'm worker: "Bob" at thread number: 0x6be0 Hi, I'm worker: "Stuart" at thread number: 0x6be0 I'm "Stuart" don't spy me so frequently boss! I'm busy in my work.......... you have spy me 1 times! I'm working at thread num : 0x36c0 I'm "Bob" don't spy me so frequently boss! I'm busy in my work.......... you have spy me 1 times! I'm working at thread num : 0x5ff0 I'm "Stuart" don't spy me so frequently boss! I'm busy in my work.......... you have spy me 2 times! I'm working at thread num : 0x36c0 I'm "Stuart" don't spy me so frequently boss! I'm busy in my work.......... you have spy me 3 times! I'm working at thread num : 0x36c0 I'm "Bob" don't spy me so frequently boss! I'm busy in my work.......... I'm "Stuart" don't spy me so frequently boss! I'm busy in my work.......... you have spy me 2 times! I'm working at thread num : 0x5ff0 you have spy me 4 times! I'm working at thread num : 0x36c0 I'm "Bob" don't spy me so frequently boss! I'm busy in my work.......... I'm "Stuart" don't spy me so frequently boss! I'm busy in my work..........
不知道你們又遇到BT的老板嗎。