版权声明 --------------------------------------------------------------------------------------------------------------------- 作者: 女儿叫老白 转载请注明出处! --------------------------------------------------------------------------------------------------------------------- 引言 ---------------------------------------------------------------- 在使用Qt开发多线程应用时,是不能在多线程中直接操作主界面的控件的,否则将导致异常。那么在多线程中,该怎样同主界面线程通信呢? 正文 ---------------------------------------------------------------- 其实,这个问题在前面章节提到过,就是通过发送自定义事件给主界面,然后主界面重写自定义事件的处理函数即可。 以前一章节的示例程序为基础,将发送数据线程改为将数据发送到主界面,不再将数据写入文件。 首先需要定义自定义事件: customevent.h #pragma once #include <QEvent> #include <QString> class CCustomEvent : public QEvent { public: CCustomEvent() Event(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 { return m_nStudentNumber; } private: qint16 m_nTeacherNumber; /// 教师人数 qint16 m_nStudentNumber; /// 学员人数 }; |
然后,为CSendThread增加接口void setObject(QObjet* pObject),用来保存主界面对话框的对象指针: #pragma once #include <QThread> QT_BEGIN_NAMESPACE class QWidget; QT_END_NAMESPACE class CSendThread : public QThread { public: CSendThread(); ~CSendThread(); virtual void run(); void setObject(QObject* pObject) { m_pObject = pObject; } private: QObject * m_pObject; }; |
然后,将发送数据线程CSendThread的run()函数修改为: void CSendThread::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(new CSendThread) { ui.setupUi(this); m_pSendThread->setObject(this); connect(ui.btnStartThread, SIGNAL(clicked()), this, SLOT(slot_startthread())); } |
然后,为CDialog增加customEvent()接口,见下述代码第9行: class CDialog : public QDialog { Q_OBJECT public: CDialog(QWidget* pParent); ~CDialog(); protected: virtual void customEvent(QEvent *event); private slots: void slot_startthread(); private: Ui::CDialogBase ui; CRecvThread* m_pRecvThread; CSendThread* m_pSendThread; }; |
编写该接口的实现代码: void CDialog::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产品开发》目录
上一节: 下一节:
|