baizy77 发表于 2019-9-16 10:08:56

KS13-02 多线程应用中如何与主界面通信

版权声明---------------------------------------------------------------------------------------------------------------------该文章原创于Qter开源社区(www.qter.org)作者: 女儿叫老白转载请注明出处!---------------------------------------------------------------------------------------------------------------------课程目录: 《Qt入门与提高-GUI产品开发》目录
网页版课程源码 提取码:1uy7

引言----------------------------------------------------------------在使用Qt开发多线程应用时,是不能在多线程中直接操作主界面的控件的,否则将导致异常。那么在多线程中,该怎样同主界面线程通信呢? 正文----------------------------------------------------------------其实,这个问题在前面章节提到过,就是通过发送自定义事件给主界面,然后主界面重写自定义事件的处理函数即可。       以前一章节的示例程序为基础,将发送数据线程改为将数据发送到主界面,不再将数据写入文件。       首先需要定义自定义事件:       customevent.h
#pragmaonce#include<QEvent>#include<QString> classCCustomEvent : public QEvent {public: CCustomEvent():QEvent(QEvent::Type(QEvent::User+1)){ ; } ~CCustomEvent() { ; }    void setTeacherNumber(quint16 n) {      m_nTeacherNumber = n;    }    quint16 getTeacherNumber() const {       return m_nTeacherNumber;     }    void setStudentNumber(quint16 n) {       m_nStudentNumber = n;     }    quint16 getStudentNumber() const { returnm_nStudentNumber; } private:    qint16 m_nTeacherNumber;   /// 教师人数    qint16 m_nStudentNumber;   /// 学员人数};
       然后,为CSendThread增加接口void setObject(QObjet* pObject),用来保存主界面对话框的对象指针:
#pragmaonce #include<QThread>QT_BEGIN_NAMESPACEclassQWidget;QT_END_NAMESPACE classCSendThread : public QThread {public:    CSendThread(); ~CSendThread(); virtual void run();    void setObject(QObject* pObject) {      m_pObject = pObject;    }private:    QObject * m_pObject;};
       然后,将发送数据线程CSendThread的run()函数修改为:
voidCSendThread::run(){    CCustomEvent* pEvent = NULL;    QString str; while (isRunning()) {                                  sleep(1);      str = QString("teacher:%1,").arg(CConfig::instance().getTeacherNumber());      str +=QString("student:%1\n").arg(CConfig::instance().getStudentNumber());            pEvent = new CCustomEvent();         pEvent->setTeacherNumber(CConfig::instance().getTeacherNumber());         pEvent->setStudentNumber(CConfig::instance().getStudentNumber());            QCoreApplication::postEvent(m_ pObject,pEvent); }}
       既然主界面CDialog要接收CSendThread对象的事件,就要把自身地址传递给CSendThread,见下述代码第8行:
CDialog::CDialog(QWidget*pParent) : QDialog(pParent), m_pRecvThread(new CRecvThread), m_pSendThread(newCSendThread) { ui.setupUi(this);    m_pSendThread->setObject(this); connect(ui.btnStartThread, SIGNAL(clicked()),this, SLOT(slot_startthread()));}
       然后,为CDialog增加customEvent()接口,见下述代码第9行:
classCDialog : public QDialog{ Q_OBJECTpublic: CDialog(QWidget* pParent); ~CDialog(); protected:    virtual void customEvent(QEvent *event); privateslots: void slot_startthread(); private:    Ui::CDialogBase ui;    CRecvThread* m_pRecvThread;    CSendThread* m_pSendThread;};
       编写该接口的实现代码:
voidCDialog::customEvent(QEvent *event) {    QString str;    CCustomEvent* pEvent = NULL;    switch (event->type()) {    case (QEvent::User + 1): {      pEvent =dynamic_cast<CCustomEvent*>(event);      if (NULL != pEvent) {            str = QString("teacher:%1,").arg(pEvent->getTeacherNumber());            str +=QString("student:%1\n").arg(pEvent->getStudentNumber());            ui.textLabel->setText(str);      }    }      break;    default:      break;    }}
结语----------------------------------------------------------------   本文又回顾了以便在多线程中通过发送自定义事件给主界面来实现操作主界面的目的。核心就是编写自定义事件类用来传递数据,然后在主界面重写void customEvent(QEvent*event)接口。    读者可以利用这种方法实现多线程应用中在非主线程中刷新主界面的功能。


《Qt入门与提高-GUI产品开发》目录
上一节:下一节:
页: [1]
查看完整版本: KS13-02 多线程应用中如何与主界面通信