如何注册 class 以便在 Qt 中的 QWebChannel 信号中使用它
How to register a class for use it in a QWebChannel signal in Qt
我正在使用带有 WebChannel 的 QT 5 与 HTML 页面进行通信。
我成功地能够传达文本和字符串。但是我想传达一些积分数据。
官方文档说
"No manual message passing and serialization of data is required,"
http://doc.qt.io/qt-5/qwebchannel.html
当我尝试发送对象或数组而不是字符串时,应用程序抛出此消息:
Don't know how to handle 'data', use qRegisterMetaType to register it.
如何使用 Point class 而不是字符串对象发出信号?或者将 class 序列化为字符串。
这是我要发送给我的 HTML
的对象
点class
class MyData{
public :
int x,y,z;
};
Q_DECLARE_METATYPE(MyData)
地图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);
};
和主要代码
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);
您只需要在广告位前的某处添加一行,如下所示:
qRegisterMetaType<Block>();
您正在做的是告诉元对象编译器 (MOC) 关于您的 class 的所有信息以及如何传递它。可以找到进一步阅读 here,其中更详细地讨论了这个问题,并给出了示例。
您还需要将类型名称的字符串表示形式作为参数传递给函数
qRegisterMetaType<MyData>("MyData");
根据 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.
在我自己的代码中,我使用 Q_DECLARE_METATYPE
来表示 class 我想存储在 QVariant
中(这个宏必须放在全局范围内)。而我 qRegisterMetaType<T>()
for classes 我想传递给 signals/slots(必须在 signal.slot 连接建立之前调用此函数)。如果只使用一个功能,我从来不需要调用两者。
因此,对于您的示例,这应该有效:
qRegisterMetaType<MyData>( "MyData" );
// then, form here, you can connect `updateData(MyData)` signal to any slot taking a MyData parameter
对于signal/slot声明:
- 如果未调用
qRegisterMetaType
,您只能使用 signal/slot 通过引用或指针传递 MyData
(将 signal
声明为 void updateData(MyData& data);
或 void updateData(MyData* data);
).然后,如果进行异步连接(如 Qt::QueuedConnection
),您必须非常小心,因为 slot
将被执行 "later",您必须保证对象引用在 [=20] 之前保持有效=] 在你发出 signal
. 后执行
- 如果调用了
qRegisterMetaType
,您可以使用 signal/slot 通过副本传递 MyData
(将 signal
声明为 void updateData(MyData data);
)。并且与通过副本传递的那些对象进行异步连接是安全的,因为 Qt 能够序列化对象(这意味着如果 slot
被执行 "later" 它最终将被调用一个全新的 MyData
从您发出信号的原始对象复制的对象....没有调用 qRegisterMetaType
,Qt 无法执行此操作 "copy").
确保在执行此操作时知道 MyData
声明(无前向声明)。
另请注意,并非所有 classes/structs 都可以通过这种方式注册,它们必须具有:
a public default constructor, a public copy constructor, and a public destructor
你的MyData
class是这样的(默认的就OK),应该能顺利运行。
我正在使用带有 WebChannel 的 QT 5 与 HTML 页面进行通信。 我成功地能够传达文本和字符串。但是我想传达一些积分数据。
官方文档说
"No manual message passing and serialization of data is required," http://doc.qt.io/qt-5/qwebchannel.html
当我尝试发送对象或数组而不是字符串时,应用程序抛出此消息:
Don't know how to handle 'data', use qRegisterMetaType to register it.
如何使用 Point class 而不是字符串对象发出信号?或者将 class 序列化为字符串。
这是我要发送给我的 HTML
的对象点class
class MyData{
public :
int x,y,z;
};
Q_DECLARE_METATYPE(MyData)
地图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);
};
和主要代码
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);
您只需要在广告位前的某处添加一行,如下所示:
qRegisterMetaType<Block>();
您正在做的是告诉元对象编译器 (MOC) 关于您的 class 的所有信息以及如何传递它。可以找到进一步阅读 here,其中更详细地讨论了这个问题,并给出了示例。
您还需要将类型名称的字符串表示形式作为参数传递给函数
qRegisterMetaType<MyData>("MyData");
根据 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.
在我自己的代码中,我使用 Q_DECLARE_METATYPE
来表示 class 我想存储在 QVariant
中(这个宏必须放在全局范围内)。而我 qRegisterMetaType<T>()
for classes 我想传递给 signals/slots(必须在 signal.slot 连接建立之前调用此函数)。如果只使用一个功能,我从来不需要调用两者。
因此,对于您的示例,这应该有效:
qRegisterMetaType<MyData>( "MyData" );
// then, form here, you can connect `updateData(MyData)` signal to any slot taking a MyData parameter
对于signal/slot声明:
- 如果未调用
qRegisterMetaType
,您只能使用 signal/slot 通过引用或指针传递MyData
(将signal
声明为void updateData(MyData& data);
或void updateData(MyData* data);
).然后,如果进行异步连接(如Qt::QueuedConnection
),您必须非常小心,因为slot
将被执行 "later",您必须保证对象引用在 [=20] 之前保持有效=] 在你发出signal
. 后执行
- 如果调用了
qRegisterMetaType
,您可以使用 signal/slot 通过副本传递MyData
(将signal
声明为void updateData(MyData data);
)。并且与通过副本传递的那些对象进行异步连接是安全的,因为 Qt 能够序列化对象(这意味着如果slot
被执行 "later" 它最终将被调用一个全新的MyData
从您发出信号的原始对象复制的对象....没有调用qRegisterMetaType
,Qt 无法执行此操作 "copy").
确保在执行此操作时知道 MyData
声明(无前向声明)。
另请注意,并非所有 classes/structs 都可以通过这种方式注册,它们必须具有:
a public default constructor, a public copy constructor, and a public destructor
你的MyData
class是这样的(默认的就OK),应该能顺利运行。