目录
- 1. 说明
- 2. 场景
- 3. 子线程更新UI的方法
- 3.1 一般做法
- 3.2 新玩法
1. 说明
Qt不允许子线程直接操作主线程UI,推荐的做法是,子线程发送信号,主线程响应该信号。其最终的效果,依旧不是子线程直接操作主线程UI。
2. 场景
假设现在有一个任务队列,队列里的每一个任务,都会在结束时,往主窗口的控制台打印一条消息。
代码如下:
class Console { public: void printMessage(const QString& msg) const { m_lineEdit->setText(msg); } protected: QLineEdit* m_lineEdit; }; void threadFunc(Console * console) { // some other codes console->printMessage("message"); } int main() { Console console; // some other codes std::thread th(threadFunc, &console); }
在上述代码中,子线程更新主线程ui界面,这种方法在Qt中是不允许的。Qt禁止子线程更新主线程UI。
3. 子线程更新UI的方法
3.1 一般做法
一般的做法是,子线程发送信号,主线程接收信号,并执行对应槽函数。上述代码按照这种方式进行改造,如下:
class Console { public slots: void printMessage(const QString& msg) const { m_lineEdit->setText(msg); } protected: QLineEdit* m_lineEdit; }; class Singal{ signals: void print(const QString&) const; public: void printMessage() const { emit print("message"); } }; int main() { Console console; Singal signal; connect(&signal, SIGNAL(print(const QString&)), &console, SLOT(printMessage(const QString&))); std::thread th(&Singal::printMessage, &signal); }
3.2 新玩法
从上面代码来看,一般做法里,代码量增加了不少。而且对现有代码的破坏性较大,这种破坏性更改,在接口类中,是难以容忍的。
为了保护接口,同时兼容信号槽方式,这里介绍一种新的方式:
class Console { public: void printMessage(const QString& msg) const { emit print(msg); } signal: void print(const QString& msg); protected slots: void slotOnPrint(const QString& msg) { m_lineEdit->setText(msg); } protected: QLineEdit* m_lineEdit; }; void threadFunc(Console * console) { // some other codes console->printMessage("message"); } int main() { Console console; // some other codes std::thread th(threadFunc, &console); }
上面介绍的这种新玩法,调用方没做任何更改,接口类(Console)的公开接口也没改,增加了一个信号和一个本身的槽函数,同时它还是线程安全的。
还没有评论,来说两句吧...