子线程通过QMetaObject::invokeMethod控制UI控件
1、注意,要调用的类型必须是信号、槽,以及Qt元对象系统能识别的类型。此外,使用Q_INVOKABLE来声明函数,也可以正确调用。
2、该方法线程安全,其他讲解看手册,就不翻译了
3、隐藏ui
QMetaObject::invokeMethod(ui_Ptr, "hide", Qt::QueuedConnection)
4、在子线程中给QListWidget子类MyListWidget使用addItems方法,当然你也可以在主线程additems。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #ifndef MYWORK_H 2 #define MYWORK_H 3 4 #include <QObject> 5 6 class MyWork : public QObject 7 { 8 Q_OBJECT 9 public: 10 explicit MyWork(void *, QObject *parent = nullptr); 11 12 public: 13 void doWork(); 14 signals: 15 void sendNum(QList<int>); 16 private: 17 void *m_p; 18 }; 19 20 #endif // MYWORK_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include "mywork.h" 2 #include<QRandomGenerator> 3 #include<QDebug> 4 #include<QThread> 5 #include"mylistwidget.h" 6 7 MyWork::MyWork(void *p, QObject *parent) : QObject(parent) 8 { 9 m_p = p; 10 } 11 12 void MyWork::doWork() 13 { 14 QStringList strList; 15 16 for(int i = 0; i < 10000; i++) 17 strList.append(QString::number(i)); 18 19 QMetaObject::invokeMethod(static_cast<MyListWidget*>(m_p), 20 "add", 21 Qt::QueuedConnection, 22 Q_ARG(QStringList, strList)); 23 24 qDebug()<<"子线程结束"<<QThread::currentThread(); 25 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include "mainwindow.h" 2 #include "ui_mainwindow.h" 3 #include"mywork.h" 4 #include"mythread.h" 5 #include "mylistwidget.h" 6 7 #include<QRandomGenerator> 8 #include<QDebug> 9 #include<QElapsedTimer> 10 11 MainWindow::MainWindow(QWidget *parent) 12 : QMainWindow(parent) 13 , ui(new Ui::MainWindow) 14 { 15 ui->setupUi(this); 16 qDebug()<<"主线程地址: "<<QThread::currentThread()<<this; 17 18 QThread *sub = new QThread; 19 MyWork *work = new MyWork(ui->listWidget); // 不能指定父对象,不然无法moveToThread 20 work->moveToThread(sub); 21 qDebug()<<"sub线程地址: "<<sub->currentThread()<<sub; 22 23 connect(ui->pushButton, &QPushButton::clicked, work, &MyWork::doWork); 24 25 sub->start(); 26 } 27 28 MainWindow::~MainWindow() 29 { 30 delete ui; 31 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #ifndef MYLISTWIDGET_H 2 #define MYLISTWIDGET_H 3 4 #include <QListWidget> 5 6 class MyListWidget : public QListWidget 7 { 8 Q_OBJECT 9 public: 10 explicit MyListWidget(QWidget *parent = nullptr); 11 12 signals: 13 14 public slots: 15 void add(QStringList str); // 用于调用additems 16 17 }; 18 19 #endif // MYLISTWIDGET_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include "mylistwidget.h" 2 3 MyListWidget::MyListWidget(QWidget *parent) : QListWidget(parent) 4 { 5 6 } 7 8 void MyListWidget::add(QStringList str) 9 { 10 this->addItems(str); 11 }
mywork.h中声明了一个add,用于调用addItems,因为QMetaObject::invokeMethod识别不到addItems。