• <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++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            Q_INVOKABLE與invokeMethod用法全解

            Posted on 2011-08-05 07:19 RTY 閱讀(1826) 評論(0)  編輯 收藏 引用 所屬分類: Qt

            請尊重原創作品和譯文。轉載請保持文章完整性,并以超鏈接形式注明原始作者地址http://blog.csdn.net/changsheng230,方便其他朋友提問和指正。

             

            Qt/Qt Quick宏淺議一文中,我們將介紹Qt中經常使用的幾個宏: Q_OBJECT, SIGNAL與SLOT, Q_SIGNALS 與 Q_SLOTS, Q_EMIT ,Q_INVOKABLE, Q_PROPERTY。相比其他宏,Q_INVOKABLE 顯得更加神秘,但Q_INVOKABLE的理解與使用變得越來越重要。本文將圍繞Q_INVOKABLE以及相對應的invokeMethod展開討論。

            Q_INVOKABLE

            #define Q_INVOKABLE

            重新回顧一下Q_INVOKABLE的定義,它在$QTDIR/src/corelib/kernel/qobjectdefs.h 中,簡單被define,目的在于讓moc識別。

            使用Q_INVOKABLE來修飾成員函數,目的在于被修飾的成員函數能夠被元對象系統所喚起。

            QMetaObject::invokeMethod

            靜態方法QMetaObject::invokeMethod() 的定義如下:

               

              1. bool QMetaObject::invokeMethod ( QObject * obj, const char * member,Qt::ConnectionType type,  
              2. QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument( 0 ), …)  
               

               

               

            invokeMethod的用法為,嘗試調用對象obj的方法member(注意member可以為信號或者是槽),如何member可以被調用,則返回真,否則返回假。QMetaObject::invokeMethod可以是異步調用,也可以是同步調用。這取決與它的連接方式Qt::ConnectionType type。如果type為Qt::DirectConnection,則為同步調用,若為Qt::QueuedConnection,則為異步調用。例如:

               

              1. QMetaObject::invokeMethod(object, "methodName",   
              2. Qt::QueuedConnection,   
              3. Q_ARG(type1, arg1),   
              4. Q_ARG(type2, arg2));  
               

               

            上述調用為異步調用。請注意,因為上面所示的參數需要被在構建事件時進行硬拷貝,參數的自定義型別所對應的類需要提供一個共有的構造函數、析構函數以及拷貝構造函數。而且必須使用注冊Qt型別系統所提供的qRegisterMetaType() 方法來注冊這一自定義型別。

            Q_INVOKABLE與QMetaObject::invokeMethod均由元對象系統喚起。這一機制在Qt C++/QML混合編程跨線程編程Qt Service Framework 以及 Qt/ HTML5混合編程以及里廣泛使用。

            Qt C++/QML混合編程

            QML中調用C++方法借助了Qt元對象系統。考慮在QML中使用Qt C++定義的方法,如下代碼所示:

             

            1. import Qt 4.7   
            2. import Shapes 5.0   //自定義模塊  
            3. Item {   
            4.     width: 300; height: 200  
            5.     Ellipse {   
            6.          x: 50; y: 35; width: 200; height: 100   
            7.         color: "blue"   
            8.          MouseArea {   
            9.             anchors.fill: parent  
            10.             // 調用C++中定義的randomColor方法   
            11.             onClicked: parent.color = parent.randomColor()    
            12.         }   
            13.     }  
            14. }  
             

             

            為了讓上述QML代碼成功的調用下面這段代碼定義的randomColor()函數,最為關鍵的一點見randomColor方法用Q_INVOKABLE 修飾。

             

            1. #include <QDeclarativeItem >  
            2. class EllipseItem : public QDeclarativeItem   
            3. {   
            4.     Q_OBJECT   
            5. public:  
            6.       Q_INVOKABLE QColor randomColor() const;  
            7.       …  
            8. }  
             

             

            更多細節,請參看我的另一篇博文:QML與C++混合編程使用

            在跨線程編程中的使用

            我們如何調用駐足在其他線程里的QObject方法呢?Qt提供了一種非常友好而且干凈的解決方案:向事件隊列post一個事件,事件的處理將以調用我們所感興趣的方法為主(當然這需要線程有一個正在運行的事件循環)。而觸發機制的實現是由moc提供的內省方法實現的。因此,只有信號、槽以及被標記成Q_INVOKABLE的方法才能夠被其它線程所觸發調用。如果你不想通過跨線程的信號、槽這一方法來實現調用駐足在其他線程里的QObject方法。另一選擇就是將方法聲明為Q_INVOKABLE,并且在另一線程中用invokeMethod喚起。

             

            更多細節,譯文事件循環與線程

            Qt Service Framework

            Qt服務框架是Qt Mobility 1.0.2版本推出的,一個服務(service)是一個獨立的組件提供給客戶端(client)定義好的操作。客戶端可以通過服務的名稱,版本號和服務的對象提供的接口來查找服務。 查找到服務后,框架啟動服務并返回一個指針。

            服務通過插件(plug-ins)來實現。為了避免客戶端依賴某個具體的庫,服務必須繼承自QObject。這樣QMetaObject 系統可以用來提供動態發現和喚醒服務的能力。要使QmetaObject機制充分的工作,服務必須滿足,其所有的方法都是通過 signal,slot,property 或invokable methodQ_INVOKEBLE來實現

            其中,最常見的與servicer交互的方法如下:

            1. QServiceManager manager;QObject *storage ;  
            2. storage = manager.loadInterface("com.nokia.qt.examples.FileStorage"); if (storage)     QMetaObject::invokeMethod(storage, "deleteFile", Q_ARG(QString, "/tmp/readme.txt"));  
            上面的代碼通過service的元對象提供的invokeMethod方法,調用文件存儲對象的deleteFile() 方法。客戶端不需要知道對象的類型,因此也沒有鏈接到具體的service庫。  當然在服務端的deleteFile方法,一定要被標記為Q_INVOKEBLE,才能夠被元對象系統識別

            Qt服務框架的一個亮點是它支持跨進程通信,服務可以接受遠程進程。在服務管理器上注冊后 進程通過signal,slot,invokable method和property來通信,就像本地對象一樣。服務可以設定為在客戶端間共享,或針對一個客戶端。  請注意,在Qt服務框架推出之前,信號、槽以及invokable method僅支持跨線程。 下圖是跨進成的服務/客戶段通信示意圖(圖片來自諾基亞論壇)。這里我們可以清楚的看到,invokable methodQ_INVOKEBLE 是跨進城、跨線程對象之間通信的重要利器。

             

            serivceFramework

            有關Qt Service Framework的更多討論和用例,請參見Qt Service Framework文檔

            久久亚洲国产精品成人AV秋霞| 性做久久久久久久久| 久久久久av无码免费网| 国产亚洲精久久久久久无码AV| 久久99国产综合精品| 久久最新免费视频| 久久久久国产一级毛片高清板| 中文字幕亚洲综合久久2| 久久精品水蜜桃av综合天堂| 久久久久人妻精品一区二区三区| 日韩人妻无码一区二区三区久久 | 亚洲AV无码久久精品蜜桃| 伊人久久一区二区三区无码| 亚洲国产天堂久久综合| 国产一区二区久久久| 久久婷婷五月综合97色直播| 97精品伊人久久久大香线蕉| 亚洲中文字幕无码一久久区| 久久精品国产亚洲av麻豆小说 | 精品无码久久久久久久动漫| 久久精品夜色噜噜亚洲A∨| 色婷婷综合久久久久中文字幕| 久久久久久久久久久精品尤物| 久久国产免费观看精品3| 国产三级精品久久| 99精品久久精品一区二区| 久久香蕉国产线看观看99| 久久露脸国产精品| 久久精品中文騷妇女内射| 国产精品免费久久久久久久久| 日韩va亚洲va欧美va久久| 久久精品国产亚洲av麻豆色欲| 国产成人无码精品久久久免费 | 韩国三级中文字幕hd久久精品| 久久一区二区三区99| 国产精品免费看久久久| 香蕉久久影院| 精品99久久aaa一级毛片| 久久天堂AV综合合色蜜桃网| 欧美久久久久久精选9999| 精品久久一区二区三区|