如何注册一个类以在Qt中的QWebChannel信号中使用它

How to register a class for use it in a QWebChannel signal in Qt

本文关键字:QWebChannel 中的 Qt 信号 注册 何注册 一个      更新时间:2023-10-16

我使用带有WebChannel的QT 5与HTML页面进行通信。我成功地传达了文本和字符串。但是我喜欢传达一些积分数据。

官方文件说

"不需要手动传递消息和数据序列化," http://doc.qt.io/qt-5/qwebchannel.html

当我尝试发送对象或数组而不是字符串时,应用程序会抛出以下消息:

不知道如何处理"数据",请使用qRegisterMetaType来注册它。

如何使用 Point 类而不是字符串对象发出信号?或者将类序列化为字符串。

这是我想发送到我的 HTML 的对象

点类

class MyData{
public :
    int x,y,z;
};
Q_DECLARE_METATYPE(MyData)

地图类

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);

每个Qt文档:

要在 QVariant 中使用类型 T,使用 Q_DECLARE_METATYPE() 是 足够。要在排队信号和插槽连接中使用类型 T, qRegisterMetaType() 必须在第一个连接之前调用 既定。

在我自己的代码中,我对要存储在QVariant中的类使用 Q_DECLARE_METATYPE(此宏必须放在全局范围内)。我qRegisterMetaType<T>()对于我想传递给信号/插槽的类(必须在建立 signal.slot 连接之前调用此函数)。如果只使用一个功能,我永远不必同时调用这两个功能。

因此,对于您的示例,这应该有效:

qRegisterMetaType<MyData>( "MyData" );
// then, form here, you can connect `updateData(MyData)` signal to any slot taking a MyData parameter

对于信号/插槽声明:

  • 如果未调用qRegisterMetaType,则只能通过引用或指针使用信号/插槽传递MyData(将signal声明为 void updateData(MyData& data);void updateData(MyData* data); )。然后,如果进行异步连接(如Qt::QueuedConnection),则必须非常小心,因为由于slot将在"稍后"执行,因此您必须保证对象引用保持有效,直到slot在您发出signal后被执行。
  • 如果调用了qRegisterMetaType,则可以使用通过副本传递MyData的信号/插槽(将signal声明为 void updateData(MyData data); )。并且与那些通过复制传递的对象进行异步连接是安全的,因为Qt能够序列化对象(这意味着如果slot"稍后"执行,它最终将被调用一个全新的MyData对象从您发出信号的原始对象复制......如果不调用qRegisterMetaType,Qt将无法执行此"复制")。

确保在执行此操作时已知MyData声明(无前向声明)。

另请注意,并非所有类/结构都可以通过这种方式注册,它们必须具有:

公共默认构造函数

、公共复制构造函数和公共析构函数

您的MyData类就是这种情况(默认的没问题),因此它应该可以顺利运行。

你只需要在你的插槽之前的某个地方有一行,就像这样:

qRegisterMetaType<Block>();

您正在做的是告诉元对象编译器 (MOC) 有关您的类以及如何传递它的所有信息。进一步的阅读可以在这里找到,其中更详细地讨论了这个问题,并给出了例子。

您还需要将类型名称的字符串表示形式作为参数传递给函数

qRegisterMetaType<MyData>("MyData");