Я использую 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);
Чтобы использовать тип 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
класс (по умолчанию все в порядке), поэтому он должен работать плавно.
Вам просто нужна строка где-то перед вашим слотом:
qRegisterMetaType<Block>();
Что вы делаете, так это рассказываете Meta Object Compiler (MOC) о вашем классе и о том, как его передать. Дальнейшее чтение можно найти Вот который обсуждает эту проблему более подробно, и приводит примеры.
Вам также необходимо передать строковое представление имени типа в качестве параметра функции
qRegisterMetaType<MyData>("MyData");