一般情況下信號槽直接連接方式不會出現問題,但是如果信號與槽在不同線程或Qt::QueuedConnection方式連接,可能會在連接期間報以下類似問題,如:
QObject::connect: Cannot queue arguments of type 'ThreadSignal'
(Make sure 'ThreadSignal' is registered using qRegisterMetaType().)
或者
QObject::connect: Cannot queue arguments of type 'BYTE[5]'
(Make sure 'BYTE[5]' is registered using qRegisterMetaType().)
或者
QObject::connect: Cannot queue arguments of type 'QMap<QString,CommDevice*>'
(Make sure 'QMap<QString,CommDevice*>' is registered using qRegisterMetaType().)
出現如此問題,在於QT對數據類型未知,按照此提示在連接信號與槽之前,調用 qRegisterMetaType()解決。直接上代碼,如下:
qRegisterMetaType<ThreadSignal>("ThreadSignal");
或者
qRegisterMetaType<BYTE * >("BYTE[5]"); //請注意這一行,關於如何注冊數組類型
或者
這種情況有點復雜,由於QMap<QString,CommDevice*> 在qRegisterMetaType<QMap<QString,CommDevice*>>("QMap<QString,CommDevice*>")會報錯,無法識別,故可才采用別名的方式:
typedef QMap<QString,CommDevice*> MP_COMMDEVICES;
然后注冊采用
qRegisterMetaType<MP_COMMDEVICES>("MP_COMMDEVICES");即可注冊成功。
關鍵點:此處的注冊語句qRegisterMetaType()一定要在connect之前執行。如果是信號槽在不同線程的情況下,則需要采用以下方式先利用信號槽調用qRegisterMetaType()注冊,然后再利用信號槽建立connect,而不是在構造函數中簡單的將qRegisterMetaType語句放在connect語句之前執行這么簡單,因為構造函數是在生成該對象的線程中執行的。具體參考以下代碼:
1 TcpConnectManage.h 2 3 #ifndef TCPCONNECTMANAGE_H 4 #define TCPCONNECTMANAGE_H 5 6 #include <QObject> 7 #include <QThread> 8 #include "Protocol.h" 9 10 11 typedef QMap<QString,CommDevice*> MP_COMMDEVICES;//QMap<QString,CommDevice*>無法在qRegisterMetaType中識別,故采用別名方式 12 13 class TcpConnectManage : public QObject 14 { 15 Q_OBJECT 16 public: 17 explicit TcpConnectManage(QObject *parent = 0); 18 ...... 19 void connectKeep(QMap<QString, Protocol *> *protocols, MP_COMMDEVICES comm_devices); 20 ...... 21 /// 22 /// \brief registerReflex 注冊反射類 23 /// 24 void registerReflex(); 25 /// 26 /// \brief createConnect 本函數配合對應的信號槽的目的主要是,為了注冊 27 /// 28 void createConnect(); 29 30 signals: 31 void sigConnectKeep(QMap<QString, Protocol *> *protocols, MP_COMMDEVICES comm_devices); 32 void sigRegisterReflex(); 33 void sigCreateConnect(); 34 public slots: 35 void sltConnectKeep(QMap<QString, Protocol *> *protocols, MP_COMMDEVICES comm_devices); 36 void sltRegisterReflex(); 37 void sltCreateConnect(); 38 }; 39 40 #endif // TCPCONNECTMANAGE_H
1 #include "TcpConnectManage.h" 2 7 8 TcpConnectManage::TcpConnectManage(QObject *parent) : 9 QObject(parent) 10 { 11 connect(this,SIGNAL(sigRegisterReflex()),this,SLOT(sltRegisterReflex())); 12 connect(this,SIGNAL(sigCreateConnect()),this,SLOT(sltCreateConnect())); 13 } 14 15 ...... 16 17 void TcpConnectManage::registerReflex() 18 { 19 emit sigRegisterReflex(); 20 } 21 22 void TcpConnectManage::createConnect() 23 { 24 emit sigCreateConnect(); 25 } 26 27 ...... 28 29 void TcpConnectManage::sltRegisterReflex() 30 { 31 //信號槽中使用的自定義類型注冊 32 qRegisterMetaType<MP_COMMDEVICES>("MP_COMMDEVICES"); 33 34 //類注冊 35 ...... 36 } 37 38 void TcpConnectManage::sltCreateConnect() 39 { 40 connect(this,SIGNAL(sigConnectKeep(QMap<QString,Protocol*>*,MP_COMMDEVICES)), 41 this,SLOT(sltConnectKeep(QMap<QString,Protocol*>*,MP_COMMDEVICES))); 42 }
注意:此處
typedef QMap<QString,CommDevice*> MP_COMMDEVICES;//QMap<QString,CommDevice*>無法在qRegisterMetaType中識別,故采用別名方式
不能為
typedef QMap<QString,CommDevice*>& MP_COMMDEVICES;//QMap<QString,CommDevice*>無法在qRegisterMetaType中識別,故采用別名方式
即參數為引用類型,會報以下錯誤

原因:template argument deduction/substitution failed 模板函數的參數類型不能通過表達式推導
關於模板參數的推導,參考:【C++】模板參數推導(template argument deduction)
http://www.cnblogs.com/visayafan/archive/2011/11/27/2265400.html
其實在信號槽連接方式使用Qt:QueuedConnection時,其中的參數完全沒有必要使用引用類型,因為此種方式下,信號參數為引用類型,則還是會另外復制一份的。

http://www.dushibaiyu.com/2015/07/qt-signals-slots-connect.html
