Qt子线程更新UI的一种新玩法

Qt子线程更新UI的一种新玩法

码农世界 2024-05-28 前端 82 次浏览 0个评论

目录

  • 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)的公开接口也没改,增加了一个信号和一个本身的槽函数,同时它还是线程安全的。

转载请注明来自码农世界,本文标题:《Qt子线程更新UI的一种新玩法》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,82人围观)参与讨论

还没有评论,来说两句吧...

Top