如果是自己定義的類型如果想使用signal/slot來傳遞的話,則沒有這麼簡單。直接使用的話,會產生下面這種錯誤:
QObject::connect: Cannot queue arguments of type 'TextAndNumber' (Make sure 'TextAndNumber' is registed using qRegisterMetaType().)
原因:當一個signal被放到隊列中(queued)時,它的參數(arguments)也會被一起一起放到隊列中(queued起來),這就意味着參數在被傳送到slot之前需要被拷貝、存儲在隊列中(queue)中;爲了能夠在隊列中存儲這些參數(argument),Qt需要去construct、destruct、copy這些對象,而爲了讓Qt知道怎樣去作這些事情,參數的類型需要使用qRegisterMetaType來註冊(如錯誤提示中的說明)
步驟:(以自定義TextAndNumber類型爲例)
自定一種類型,在這個類型的頂部包含:#include <QMetaType>
在類型定義完成後,加入聲明:Q_DECLARE_METATYPE(TextAndNumber);
在main()函數中註冊這種類型:qRegisterMetaType<TextAndNumber>("TextAndNumber");
如果還希望使用這種類型的引用,可同樣要註冊:qRegisterMetaType<TextAndNumber>("TextAndNumber&");
#include <QMetaType>
//必須包含QMetaType,否則會出現下面錯誤:
//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&)));