Согласно документам классы, которые наследуются от QObject
, не могут иметь конструктор копирования или оператор присваивания:
Нет конструктора копирования или оператора присваивания
QObject не имеет ни конструктора копирования, ни оператора присваивания.Это по замыслу.На самом деле они объявлены, но в закрытом разделе с макросом Q_DISABLE_COPY ().Фактически, все классы Qt, производные от QObject (прямые или косвенные), используют этот макрос, чтобы объявить их конструктор копирования и оператор присваивания закрытыми.Обоснование можно найти в обсуждении Identity vs Value на странице объектной модели Qt.
Основным следствием является то, что вы должны использовать указатели на QObject (или на ваш подкласс QObject), где у вас может возникнуть искушение использоватьВаш подкласс QObject в качестве значения.Например, без конструктора копирования вы не можете использовать подкласс QObject в качестве значения, которое будет храниться в одном из классов контейнера.Вы должны хранить указатели.
С другой стороны, если вы хотите, чтобы класс, унаследованный от QObject, поддерживал QMetaType, чтобы использовать его как QVariant, вы должны передать его указателю, потому что, как было отмечено,QObjects не имеют конструктора копирования, но указатели копируются.
//mydata.h
#ifndef MYDATA_H
#define MYDATA_H
#include <QObject>
class MyData : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ get_name WRITE set_name NOTIFY nameChanged)
public:
explicit MyData(QObject *parent = nullptr);
MyData(const QString & name);
~MyData() override = default;
signals:
void nameChanged();
public slots:
void set_name(const QString &name);
QString get_name();
private:
QString _name;
};
Q_DECLARE_METATYPE(MyData*)
#endif // MYDATA_H
//mydata.cpp
#include "mydata.h"
MyData::MyData(QObject *parent) : QObject(parent)
{}
MyData::MyData(const QString & name)
: _name(name){}
void MyData::set_name(const QString &name)
{
if(_name == name) return;
_name = name;
emit nameChanged();
}
QString MyData::get_name()
{return _name;}
Вы указываете, что setValue работает, вы купили, что он работает?, кроме того, этот метод используется для типов, которые неподдерживать QVariant, поэтому они, вероятно, примут любой тип данных, что нужно сделать, чтобы передать указатель:
MyData test1("Hi");
MyData test2("Hello");
QMap<QString, QVariant> mymap;
QVariant qvtest1 = QVariant::fromValue(&test1);
QVariant qvtest_1, qvtest_2;
qvtest_1.setValue(&test1);
qvtest_2.setValue(&test2);
С другой стороны, setContextProperty, это принимает QVariant или указатель на QObjectи в первом случае вы передаете QObject, правильная вещь - передать указатель, во втором случае вы передаете QVariant, чтобы не возникало проблем с его копированием.
engine->rootContext()->setContextProperty("test1", &test1);
engine->rootContext()->setContextProperty("mymap", mymap);
В заключение выдолжен передать объект, копируемый в setContextProperty.
qmlRegisterType
только записи о том, что тип может быть передан через сигналы, ноэто не гарантирует его работоспособность, это необходимое условие, но его недостаточно, поскольку оно не копируется, поэтому вы должны использовать MyData*
.