• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 319, comments - 22, trackbacks - 0, articles - 11
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            Qt元類型(MetaType)注冊(cè)門

                  昨天調(diào)試項(xiàng)目時(shí),突然發(fā)現(xiàn)如下消息:

            QObject::connect: Cannot queue arguments of type 'ERROR_LEVEL'
            (Make sure 'ERROR_LEVEL' is registered using qRegisterMetaType().)

            其中ERROR_LEVEL只是我定義的枚舉類型即enum ERROR_LEVEL。然后在Qt的信號(hào)-槽函數(shù)的參數(shù)中使用了這個(gè)枚舉型,在發(fā)送信號(hào)時(shí)就出現(xiàn)了上述警告。上面警告的大概意思是信號(hào)隊(duì)列中無法使用 ERROR_LEVEL類型,要使用qRegisterMetaType()注冊(cè)該類型后方可使用。

                  通常使用的connect,實(shí)際上最后一個(gè)參數(shù)使用的是Qt::AutoConnection類型:

            bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoConnection )

            Qt支持6種連接方式,其中3中最主要:

            • Qt::DirectConnection(直連方式)

                  當(dāng)信號(hào)發(fā)出后,相應(yīng)的槽函數(shù)將立即被調(diào)用。emit語句后的代碼將在所有槽函數(shù)執(zhí)行完畢后被執(zhí)行。(信號(hào)與槽函數(shù)關(guān)系類似于函數(shù)調(diào)用,同步執(zhí)行

            • Qt::QueuedConnection(排隊(duì)方式)

                  當(dāng)信號(hào)發(fā)出后,排隊(duì)到信號(hào)隊(duì)列中,需等到接收對(duì)象所屬線程的事件循環(huán)取得控制權(quán)時(shí)才取得該信號(hào),調(diào)用相應(yīng)的槽函數(shù)。emit語句后的代碼將在發(fā)出信號(hào)后立即被執(zhí)行,無需等待槽函數(shù)執(zhí)行完畢。(此時(shí)信號(hào)被塞到信號(hào)隊(duì)列里了,信號(hào)與槽函數(shù)關(guān)系類似于消息通信,異步執(zhí)行

            • Qt::AutoConnection(自動(dòng)方式)

                  Qt的默認(rèn)連接方式,如果信號(hào)的發(fā)出和接收這個(gè)信號(hào)的對(duì)象同屬一個(gè)線程,那個(gè)工作方式與直連方式相同;否則工作方式與排隊(duì)方式相同。

                  我的項(xiàng)目中的確跨線程使用了ERROR_LEVEL為參數(shù)類型的信號(hào),因此使用的應(yīng)當(dāng)是排隊(duì)方式的信號(hào)-槽機(jī)制,出現(xiàn)“隊(duì)列中無法使用ERROR_LEVEL類型”的警告信息就可以理解了。放狗搜了一圈,有篇文章提供了個(gè)這樣的解決方案:

            connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)),
                        this,SLOT(sendRes(QUuid,QByteArray,bool)));
            改為:
            connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)),
                        this,SLOT(sendRes(QUuid,QByteArray,bool)), Qt::DirectConnection);

            這樣做的確能使警告信息消失,因?yàn)镼t官方文檔寫了:

            With queued connections, the parameters must be of types that are known to Qt's meta-object system, because Qt needs to copy the arguments to store them in an event behind the scenes.

            即使用排隊(duì)方式的信號(hào)-槽機(jī)制,Qt的元對(duì)象系統(tǒng)(meta-object system)必須知道信號(hào)傳遞的參數(shù)類型。這里手動(dòng)改為直連方式,Qt的元對(duì)象系統(tǒng)就不必知道參數(shù)類型了,于是警告信息消失。但這樣做是不安全的,見Qt官方文檔:

            Be aware that using direct connections when the sender and receiver live in different threads is unsafe if an event loop is running in the receiver's thread, for the same reason that calling any function on an object living in another thread is unsafe.

                  因此,咱還是老老實(shí)實(shí)地用qRegisterMetaType()注冊(cè)類型吧,見代碼:

            頭文件

            /*! \file errorlevel.h*/
            
            #ifndef ERRORLEVEL_H
            
            #define ERRORLEVEL_H
            
            
            
            /*! \enum ERROR_LEVEL
            
             * 錯(cuò)誤等級(jí)的定義。通常用來在傳遞錯(cuò)誤消息時(shí)標(biāo)記錯(cuò)誤的等級(jí)。
            
             */
            
            enum ERROR_LEVEL
            
            {
            
                NORMAL,  /*!< 普通錯(cuò)誤,通常不需要處理,可以記錄或者顯示錯(cuò)誤消息。*/
            
                CRITICAL /*!< 嚴(yán)重錯(cuò)誤,需要緊急處理,如果沒有妥善處理,可能導(dǎo)致后續(xù)操作失敗。*/
            
            };
            
            
            
            #endif // ERRORLEVEL_H

            cpp文件

            /*! \file errorlevel.cpp*/
            
            #include "errorlevel.h"
            
            
            
            /*! 模板函數(shù)顯式實(shí)例化,注冊(cè)ERROR_LEVEL到元對(duì)象系統(tǒng)。這樣才可以在信號(hào)-槽
            
             * 隊(duì)列里使用ERROR_LEVEL類型參數(shù)。
            
             */
            
            int i = qRegisterMetaType<ERROR_LEVEL>("ERROR_LEVEL");
            元類型注冊(cè)方法受益于這篇文章。
            中文字幕久久亚洲一区| 日产精品久久久一区二区| 久久久久无码专区亚洲av| 欧美伊人久久大香线蕉综合69| 亚洲а∨天堂久久精品| 日产精品久久久久久久| 国产一区二区三精品久久久无广告 | 中文字幕一区二区三区久久网站 | 四虎国产精品成人免费久久| 久久午夜夜伦鲁鲁片免费无码影视| 精品久久久久久亚洲精品| 久久精品视屏| 国产午夜福利精品久久2021| 久久精品国产一区二区三区不卡| 久久影院综合精品| 色青青草原桃花久久综合| 大香网伊人久久综合网2020| 久久久久亚洲AV无码永不| 无码精品久久一区二区三区 | 久久久WWW成人| 一本久久久久久久| 国产一久久香蕉国产线看观看| 伊人久久大香线蕉综合热线| Xx性欧美肥妇精品久久久久久| 久久精品国产亚洲77777| 伊人色综合久久天天人手人婷| 久久午夜综合久久| 国内精品伊人久久久久影院对白| 久久99国产精品久久| 久久99免费视频| 国产精品美女久久久m| 麻豆亚洲AV永久无码精品久久| 欧美亚洲国产精品久久高清| 久久婷婷五月综合成人D啪| 久久成人永久免费播放| 久久99精品国产麻豆不卡| 国产免费福利体检区久久| 久久国产成人亚洲精品影院| 久久99国产精品成人欧美| 亚洲精品乱码久久久久久蜜桃| 久久精品极品盛宴观看|