如何注册 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

你的MyDataclass是这样的(默认的就OK),应该能顺利运行。