Im using QT 5 with a WebChannel to communicate with a HTML Page. I successfully able to communicate texts and strings. however i woud like to communicate some points data.
the official documentation says
"No manual message passing and serialization of data is required," http://doc.qt.io/qt-5/qwebchannel.html
When i try to send a object or an array, instead of a string, the application throw this message:
Don't know how to handle 'data', use qRegisterMetaType to register it.
How can I emit a signal with a Point class instead of a string object? Or to serialize a class to a string.
This is the object that i would like to send to my HTML
Point class
class MyData{
public :
int x,y,z;
};
Q_DECLARE_METATYPE(MyData)
Map class
class MyMap : public QObject{
Q_OBJECT
public:
explicit MyMap ();
signals:
updateText(const QString &text); // registered
updateData(MyData &data); // Don't know how to handle 'data', use qRegisterMetaType to register it.
public slots:
receiveText(const QString &text);
};
and the main code
qRegisterMetaType<MyData>();
// setup the channel
QWebChannel channel;
QObject::connect(&clientWrapper, &WebSocketClientWrapper::clientConnected, &channel, &QWebChannel::connectTo);
// setup the dialog and publish it to the QWebChannel
channel.registerObject(QStringLiteral("map"), &map);
map.updateText("text");
MyData data;
data.x=10;
data.y=12;
data.z=13;
map.updateData(data);
Per Qt documentation:
To use the type T in QVariant, using Q_DECLARE_METATYPE() is sufficient. To use the type T in queued signal and slot connections, qRegisterMetaType() must be called before the first connection is established.
In my own code, I use Q_DECLARE_METATYPE
for classes I want to store in a QVariant
(this macro has to by put at global scope). And I qRegisterMetaType<T>()
for classes I want to be passed to signals/slots (this function has to be called before the signal.slot connection is made). I never had to call both if using only one feature.
So, for your example, this should work:
qRegisterMetaType<MyData>( "MyData" );
// then, form here, you can connect `updateData(MyData)` signal to any slot taking a MyData parameter
For signal/slot declaration:
qRegisterMetaType
was not called, you can only use signal/slot passing MyData
by reference or pointer (declare the signal
as void updateData(MyData& data);
or void updateData(MyData* data);
). Then, you must be very careful if doing asynchonous connection (like Qt::QueuedConnection
) because, as the slot
will be executed "later", you must guarantee that object reference remains valid untill the slot
gets executed after you emited the signal
.qRegisterMetaType
was called, you can use signal/slot passing MyData
by copy (declare the signal
as void updateData(MyData data);
). And it's safe to do asynchonous connection with those objects passed by copy as Qt is able to serialize the object (meaning that if the slot
is executed "later" it will in the end be called with a brand new MyData
object copied from the original one you emited the signal with....without qRegisterMetaType
being called, Qt is unable to do this "copy").Make sure MyData
declaration is known when you do this (no forward declaration).
Note also that not all classes/structs can be registered this way, they must have:
a public default constructor, a public copy constructor, and a public destructor
It's the case for your MyData
class (default ones are OK), so it should work smoothly.