国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

《OpenCV》Part11 OpenCV3.1.0 Qt中的信號(hào)槽函數(shù)傳遞cv::Mat格式參數(shù)

2019-11-08 20:25:59
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

《OpenCV》Part11 OpenCV3.1.0 Qt中的信號(hào)槽函數(shù)傳遞cv::Mat格式參數(shù)

一、信號(hào)傳送問(wèn)題

1、寫(xiě)Qt的多線程程序,用到信號(hào)槽函數(shù)傳遞cv::Mat格式的參數(shù),編譯通過(guò),但是debug時(shí)提示下列錯(cuò)誤:

QObject::connect: Cannot queue arguments of type 'Mat'(Make sure 'Mat' is registered using qRegisterMetaType().)意思是說(shuō),信號(hào)槽隊(duì)列中的數(shù)據(jù)類(lèi)型必須是系統(tǒng)能識(shí)別的元類(lèi)型,不然得用qRegisterMetaType()進(jìn)行注冊(cè)。

原因:當(dāng)一個(gè)signal被放到隊(duì)列中(queued)時(shí),它的參數(shù)(arguments)也會(huì)被一起一起放到隊(duì)列中(queued起來(lái)),這就意味著參數(shù)在被傳送到slot之前需要被拷貝、存儲(chǔ)在隊(duì)列中(queue)中;為了能夠在隊(duì)列中存儲(chǔ)這些參數(shù)(argument),Qt需要去construct、destruct、copy這些對(duì)象,而為了讓Qt知道怎樣去作這些事情,參數(shù)的類(lèi)型需要使用qRegisterMetaType來(lái)注冊(cè)(如錯(cuò)誤提示中的說(shuō)明)步驟:(以自定義TextAndNumber類(lèi)型為例)自定一種類(lèi)型,在這個(gè)類(lèi)型的頂部包含:#include <QMetaType>在類(lèi)型定義完成后,加入聲明:Q_DECLARE_METATYPE(TextAndNumber);在main()函數(shù)中注冊(cè)這種類(lèi)型:qRegisterMetaType<TextAndNumber>("TextAndNumber");如果還希望使用這種類(lèi)型的引用,可同樣要注冊(cè):qRegisterMetaType<TextAndNumber>("TextAndNumber&");

#include <QMetaType> //必須包含QMetaType,否則會(huì)出現(xiàn)下面錯(cuò)誤: //error: expected constructor, destructor, or type conversion before ‘;’ token #include <QString> class TextAndNumber { public: TextAndNumber(); TextAndNumber(int, QString); int count(); QString text(); PRivate: int m_count; QString m_text; }; Q_DECLARE_METATYPE(TextAndNumber); #endif // TEXTANDNUMBER_H int main(int argc, char *argv[]) { Qapplication app(argc, argv); qRegisterMetaType<TextAndNumber>("TextAndNumber"); qRegisterMetaType<TextAndNumber>("TextAndNumber&"); TextDevice device; TextThread foo("foo"), bar("bar"); QObject::connect(&foo, SIGNAL(writeText(TextAndNumber&)), &device, SLOT(write(TextAndNumber&))); QObject::connect(&bar, SIGNAL(writeText(TextAndNumber&)), &device, SLOT(write(TextAndNumber&)));上面是解決方法和步驟。網(wǎng)上對(duì)這個(gè)問(wèn)題的解決有兩種方案,除了上述的方法外,還有一種簡(jiǎn)單粗暴的方法,但是可能會(huì)造成風(fēng)險(xiǎn)。

———————————————————————————————————————————————————

二、解決方法:第一種注冊(cè)法:qRegisterMetatType<MoSystemLog>("MoSystemLog")第二種修改Connect,加一個(gè)屬性Qt::directConnection.connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)),this,SLOT(sendRes(QUuid,QByteArray,bool)),

Qt::DirectConnection);三、方法解釋?zhuān)?、第一種解決方法,即使用排隊(duì)方式的信號(hào)-槽機(jī)制,Qt的元對(duì)象系統(tǒng)(meta-object system)必須知道信號(hào)傳遞的參數(shù)類(lèi)型。這樣元系統(tǒng)可以將信號(hào)參數(shù)COPY下來(lái),放在隊(duì)列中等待事件喚醒,供槽函數(shù)調(diào)用。Just a note here, if you would have to pass custom data types between threads in Qt. As we know, a signal-slot connection is then (by default) of type Qt::QueuedConnection. Because in such a situation Qt needs to store passed parameters for a while, it creates their temporary copies. If it doesn’t recognize the passed data type, throws out an error:2、第二種方法,直接調(diào)用對(duì)方槽函數(shù),不需要保存參數(shù)。但是官方認(rèn)為這樣做有風(fēng)險(xiǎn)。四、背景知識(shí):1、首先要了解enum Qt::ConnectionTypeQt支持6種連接方式,其中3種最主要:Qt::DirectConnection(直連方式)當(dāng)信號(hào)發(fā)出后,相應(yīng)的槽函數(shù)將立即被調(diào)用。emit語(yǔ)句后的代碼將在所有槽函數(shù)執(zhí)行完畢后被執(zhí)行。(信號(hào)與槽函數(shù)關(guān)系類(lèi)似于函數(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語(yǔ)句后的代碼將在發(fā)出信號(hào)后立即被執(zhí)行,無(wú)需等待槽函數(shù)執(zhí)行完畢。(此時(shí)信號(hào)被塞到信號(hào)隊(duì)列里了,信號(hào)與槽函數(shù)關(guān)系類(lèi)似于消息通信,異步執(zhí)行)Qt::AutoConnection(自動(dòng)方式)Qt的默認(rèn)連接方式,如果信號(hào)的發(fā)出和接收這個(gè)信號(hào)的對(duì)象同屬一個(gè)線程,那個(gè)工作方式與直連方式相同;否則工作方式與排隊(duì)方式相同。Qt官方文檔中寫(xiě)明: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. If you try to use a queued connection and get the error messageQObject::connect: Cannot queue arguments of type 'MyType'callqRegisterMetaType() to register the data type before you establish the connection.注意上面紫色的內(nèi)容。connect的第五個(gè)參數(shù)用于指定反應(yīng)速度:若將: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);可解決因信號(hào)沒(méi)有及時(shí)發(fā)送,致使connect的接收方的槽不能作進(jìn)一步處理,但是有風(fēng)險(xiǎn)。

———————————————————————————————————————————————————

對(duì)于結(jié)構(gòu)體的信號(hào)槽傳輸,這里也給出一個(gè)例子。

解決方案:將結(jié)構(gòu)體搬出類(lèi),而不是寫(xiě)在類(lèi)public里面,可以寫(xiě)在同一個(gè)頭文件中。例子:

#include <QtGui/QApplication>#include <QVariant>  //*.hstructstruct1{    inta;    doubleb;};  structstruct2{    struct1 s;    intc;};  Q_DECLARE_METATYPE(struct1) //struct1與struct2 誰(shuí)先誰(shuí)后,沒(méi)有影響Q_DECLARE_METATYPE(struct2) class Data(){   public:        int x,y;} // *.cpp int main(int argc,char *argv[]){    QApplication a(argc, argv);    struct1 v1 = {1, 2.0};    QVariant var1;    var1.setValue(v1);      if(var1.canConvert<struct1>())   //判斷能否轉(zhuǎn)化為相應(yīng)類(lèi)型    {        struct1 v11 = var1.value<struct1>();    }      struct2 v2 = {{2, 3.0}, 5};    QVariant var2;      if(var2.canConvert<struct2>())    {        var2.setValue(v2);        struct2 v22 = var2.value<struct2>();    }    returna.exec();} 

結(jié)束語(yǔ):將結(jié)構(gòu)體搬出類(lèi),而不是寫(xiě)在類(lèi)public里面,可以寫(xiě)在同一個(gè)頭文件中。這個(gè)注冊(cè)函數(shù)暫時(shí)還沒(méi)用到,看看宏定義,Q_DECLARE_METATYPE(),里面好像已近帶了這個(gè)注冊(cè)功能。qRegisterMetaType<QVariant>("QVariant"); //寫(xiě)在構(gòu)造函數(shù)里


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 定日县| 宣汉县| 秭归县| 绿春县| 凤城市| 宝坻区| 平泉县| 鞍山市| 潍坊市| 曲水县| 盘山县| 米易县| 无棣县| 南宫市| 和顺县| 龙门县| 大渡口区| 阆中市| 岚皋县| 东台市| 石城县| 根河市| 汉寿县| 都江堰市| 鸡西市| 建平县| 芦溪县| 滁州市| 永新县| 元谋县| 久治县| 六盘水市| 襄樊市| 北安市| 佛冈县| 安仁县| 临海市| 富宁县| 克什克腾旗| 三明市| 龙门县|