zoukankan      html  css  js  c++  java
  • 关于Qt在子线程中使用QMessageBox的折衷方法

    Qt将所有GUI相关的处理都限制在主线程中,这么做有助于防止意想不到的访问冲突产生,但也限制了线程中某些简单的UI交互的实现,比如QMessageBox。

    因为QMessageBox必须在主线程中打开,为了使用它,便不得不自己动手实现一些信号和槽,从而增加了自己代码的复杂度。为降低使用QMessageBox时的设计负担,本文从QThread类继承一个新类MsgBoxThread,将这些实现细节封装为MsgBoxThread的成员函数about、aboutQt、critical、information、question、warning,分别与QMessageBox的静态成员about、aboutQt、critical、information、question、warning对应,使用时可从该类继承子类,并在run函数中使用这些函数:

    #include <QThread>
    #include <QMessageBox>
    
    class MsgBoxThread : public QThread
    {
       Q_OBJECT
       typedef enum {
          mbt_about = 0,
          mbt_aboutqt = 1,
          mbt_critical = 2,
          mbt_information = 3,
          mbt_question = 4,
          mbt_warning = 5
       } MSGBOXTYPE;
    protected:
       int m_btnres;
       void about(QWidget * parent, const QString &title, const QString &text) {
          emit msgbox_sig(mbt_about, parent, title, text, QMessageBox::NoButton, QMessageBox::NoButton);
       }
    
       void aboutQt(QWidget *parent, const QString &title = QString()) {
          emit msgbox_sig(mbt_aboutqt, parent, title, tr(""), QMessageBox::NoButton, QMessageBox::NoButton);
       }
    
       int critical(QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons defaultButton = QMessageBox::NoButton) {
          emit msgbox_sig(mbt_critical, parent, title, text, buttons, defaultButton);
          return m_btnres;
       }
    
       int information(QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons defaultButton = QMessageBox::NoButton)
       {
          emit msgbox_sig(mbt_information, parent, title, text, buttons, defaultButton);
          return m_btnres;
       }
    
       int question(QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No), QMessageBox::StandardButtons defaultButton = QMessageBox::NoButton) {
          emit msgbox_sig(mbt_question, parent, title, text, buttons, defaultButton);
          return m_btnres;
       }
    
       int warning(QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons defaultButton = QMessageBox::NoButton) {
          emit msgbox_sig(mbt_warning, parent, title, text, buttons, defaultButton);
          return m_btnres;
       }
    
    
    public:
       MsgBoxThread(QObject * parent = 0)
          :QThread(parent), m_btnres(QMessageBox::NoButton) {
          qRegisterMetaType<QMessageBox::StandardButtons>("QMessageBox::StandardButtons");
          connect(this, SIGNAL(msgbox_sig(MSGBOXTYPE, QWidget *, const QString, const QString, QMessageBox::StandardButtons, QMessageBox::StandardButtons)), SLOT(on_information(MSGBOXTYPE, QWidget *, const QString , const QString, QMessageBox::StandardButtons , QMessageBox::StandardButtons )), Qt::BlockingQueuedConnection);
       }
    signals:
        void msgbox_sig(MSGBOXTYPE type, QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButtons defaultButton);
    
    private slots:
        void on_msgbox(MSGBOXTYPE type, QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButtons defaultButton) {
           switch(type) {
           case mbt_about:
              QMessageBox::about(parent,title,text);
              break;
           case mbt_aboutqt:
              QMessageBox::aboutQt(parent, title);
              break;
           case mbt_critical:
              m_btnres = QMessageBox::critical(parent, title, text, buttons, defaultButton);
              break;
           case mbt_information:
              m_btnres = QMessageBox::information(parent, title, text, buttons, defaultButton);
              break;
           case mbt_question:
              m_btnres = QMessageBox::question(parent, title, text, buttons, defaultButton);
              break;
           case mbt_warning:
              m_btnres = QMessageBox::warning(parent, title, text, buttons, defaultButton);
              break;
           default:
              Q_ASSERT_X(false,"QMessageBox in thread","invalid box type specified.");
           }
        }
    };

    原理:

    自定义的MsgBoxThread类继承自QThread类,其中声明了可在子线程中发射的信号msgbox_sig,并在MsgBoxThread的构造函数中将该信号以阻塞模式(Qt::BlockingQueuedConnection)连接到私有槽函数on_msgbox。因为槽函数的父对象在主线程中创建,这保证了信号msgbox_sig在主线程的事件循环中执行;又由于槽函数on_msgbox采用组色模式连接,使得子线程在调用了这些封装函数(about、aboutQt、information、critical、warning)后会等待主线程的槽函数执行并返回后才会继续执行;综上,即可保证使用QMessageBox实现简单的UI交互,又不违反Qt的GUI相关处理必须在主线程中的限制。

    参考:http://blog.csdn.net/johnyork/article/details/46419185

  • 相关阅读:
    react-router刷新页面Cannot GET 问题
    react学习之弹出层
    react学习之js-xlsx导入和导出excel表格
    c#串口通信并处理接收的多个参数
    react与微信小程序
    promise知识点小结
    汇编命令小记
    Firebase-config 在android中的使用
    python:html元素解析
    Toast实现源码解析
  • 原文地址:https://www.cnblogs.com/findumars/p/4792204.html
Copyright © 2011-2022 走看看