Как зарегистрировать класс для использования его в сигнале QWebChannel в Qt

Я использую QT 5 с веб-каналом для связи с HTML-страницей.
Я успешно могу общаться тексты и строки. Однако я хотел бы сообщить некоторые данные точек.

официальная документация гласит

«Не требуется ручная передача сообщений и сериализация данных».http://doc.qt.io/qt-5/qwebchannel.html

Когда я пытаюсь отправить объект или массив вместо строки, приложение выдает следующее сообщение:

Не знаете, как обрабатывать «данные», используйте qRegisterMetaType, чтобы зарегистрировать его.

Как я могу излучать сигнал с помощью класса Point вместо строкового объекта? Или сериализовать класс в строку.

Это объект, который я хотел бы отправить в мой HTML

Point class

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

3

Решение

в Документация Qt:

Чтобы использовать тип T в QVariant, используйте Q_DECLARE_METATYPE ()
достаточно. Чтобы использовать тип T в подключенных к очереди сигнальных и слот-соединениях,
qRegisterMetaType () должен быть вызван до того, как первое соединение
установлено.

В своем собственном коде я использую Q_DECLARE_METATYPE для классов, которые я хочу хранить в QVariant (этот макрос должен быть выставлен в глобальном масштабе). И я 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 класс (по умолчанию все в порядке), поэтому он должен работать плавно.

1

Другие решения

Вам просто нужна строка где-то перед вашим слотом:

qRegisterMetaType<Block>();

Что вы делаете, так это рассказываете Meta Object Compiler (MOC) о вашем классе и о том, как его передать. Дальнейшее чтение можно найти Вот который обсуждает эту проблему более подробно, и приводит примеры.

0

Вам также необходимо передать строковое представление имени типа в качестве параметра функции

qRegisterMetaType<MyData>("MyData");
0
По вопросам рекламы [email protected]