Как создать новую копию QQuickItem с нуля на стороне C++ с теми же свойствами, что и у существующей

У меня есть QQuickItem, полученный со стороны С++, как это.

QQuickItem * my_item = qmlEngine->rootObjects()[0]->findChild<QQuickItem*>("ItemObjectName");

my_item действителен и имеет все установленные для него свойства.

Сценарий
У меня есть 2 окна, которым нужно, чтобы это QQuickItem отображалось попеременно. Я хочу отобразить это my_item в другом окне. Это прекрасно работает, пока я устанавливаю Parent my_item в другое окно.

// the_other_window is a QQuickWindow
QQuickWindow * the_other_window;

// here I set parent
my_item->setParentItem(the_other_window->contentItem());

Это требует, чтобы я снова сделал setParentItem обратно в исходное окно my_item, иначе оно станет невидимым в исходном окне. Это работает, но дает мне ненужную зависимость. Вместо этого я пытаюсь создать копию QQuickItem и сделать на ней setParentItem. Скопировав так:

QQuickItem * item_copy = new QQuickItem(my_item);

Вопрос: я хочу сделать item_copy таким же, как my_item. Я узнал, что QQuickItem нельзя скопировать. Итак, вы хотите установить все свойства my_item в item_copy. Таким образом воссоздавая my_item с нуля. Как я могу это сделать? Какие свойства следует копировать в первую очередь? ширина, высота, x, y и что еще?

Есть ли способ скопировать все действительные свойства в этот новый, не копируя каждое по одному?


person TheWaterProgrammer    schedule 08.09.2017    source источник
comment
Текущее решение для родителей имеет смысл? doc.qt.io/qt-5/qtquick-visualcanvas-visualparent. html   -  person ManuelH    schedule 08.09.2017


Ответы (1)


Чтобы скопировать все свойства, вы должны использовать metaobject(), благодаря этому мы получаем свойства и можем копировать их, как показано ниже. Примечание: не все свойства можно записать, для этого проверяем методом isWritable():

QQuickItem *copyQQuickItem(QQuickItem *item){
    QQuickItem *item_Copy = new QQuickItem;

    const QMetaObject *mo = item->metaObject();

    for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i){
        if(mo->property(i).isWritable()){
            const char* name = mo->property(i).name();
            item_Copy->setProperty(name, item->property(name));
        }
    }
    return item_Copy;
}

Пример:

QQuickItem * my_item = engine.rootObjects()[0]->findChild<QQuickItem*>("ItemObjectName");
QQuickItem *item_copy = copyQQuickItem(my_item);

const QMetaObject *mo = my_item->metaObject();

for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i){
    if(mo->property(i).isWritable()){
        const char* name = mo->property(i).name();
        qDebug()<<name<<my_item->property(name)<<item_copy->property(name);
        Q_ASSERT(my_item->property(name)==item_copy->property(name));
    }
}

Выход:

parent QVariant(QQuickItem*, QQuickRootItem(0x55975cfdf520)) QVariant(QQuickItem*, QQuickRootItem(0x55975cfdf520))
x QVariant(double, 0) QVariant(double, 0)
y QVariant(double, 0) QVariant(double, 0)
z QVariant(double, 0) QVariant(double, 0)
width QVariant(double, 100) QVariant(double, 100)
height QVariant(double, 100) QVariant(double, 100)
opacity QVariant(double, 1) QVariant(double, 1)
enabled QVariant(bool, true) QVariant(bool, true)
visible QVariant(bool, true) QVariant(bool, true)
state QVariant(QString, "") QVariant(QString, "")
baselineOffset QVariant(double, 0) QVariant(double, 0)
clip QVariant(bool, false) QVariant(bool, false)
focus QVariant(bool, false) QVariant(bool, false)
activeFocusOnTab QVariant(bool, false) QVariant(bool, false)
rotation QVariant(double, 0) QVariant(double, 0)
scale QVariant(double, 1) QVariant(double, 1)
transformOrigin QVariant(int, 4) QVariant(int, 4)
smooth QVariant(bool, true) QVariant(bool, true)
antialiasing QVariant(bool, false) QVariant(bool, false)
implicitWidth QVariant(double, 0) QVariant(double, 0)
implicitHeight QVariant(double, 0) QVariant(double, 0)
person eyllanesc    schedule 08.09.2017
comment
копия работает отлично. Я принял ответ за это. но выполнение setParentItem на item_copy не отображает его во втором окне. может это отдельная проблема. Я пытался позвонить item_copy->setVisible(true). Даже это не заставляет item_copy отображаться во втором окне. Любые предложения по этому поводу, пожалуйста? - person TheWaterProgrammer; 08.09.2017