Как получить переведенные значения X и Y, примененные к QQuickItem на стороне C++

У меня есть следующий QML Rectangle, у которого есть родительский элемент. Самое важное, что следует отметить, это то, что он применяет элемент Translate QML который я изо всех сил пытаюсь понять, что именно он делает с элементом QML и его дочерними элементами, к которым он применяется.

Код:

Window {
    id: main_window
    width: 640
    height: 480
    visible: true

    Item {
        id: rect_parent
        objectName: "rect_parent_object"
        x: 0
        y: 0
        width: parent.width
        height: parent.height
        transform: Translate {x: -20; y: -30}

        Rectangle {
            id: rect
            objectName: "rect_object"
            x: parent.width/2
            y: parent.height/2
            width: parent.width/3
            height: parent.height/3
            color: "red"
        }
    }
}

rect_parent имеет свойство transform: Translate, как вы видите в приведенном выше коде. Ниже приведен перевод X Y, который применяется к нему.

transform: Translate {x: -20; y: -20}

В части C++ моего кода в main.cpp я получаю QQuickItem следующим образом.

QQuickItem *rectQuickItem = qml_engine->rootObjects()[0]->findChild<QQuickItem*>("rectObject");
QQuickItem *rectQuickItemParent = qml_engine->rootObjects()[0]->findChild<QQuickItem*>("rectParentObject");

Да, я могу получить x и y из rectQuickItem следующим образом.

QQuickItem *rectQuickItemParent = qml_engine->rootObjects()[0]->findChild<QQuickItem*>("rectParentObject");
qreal item_x = rectQuickItem->x();
qreal item_y = rectQuickItem->y();

Вопрос:
Но как мне получить переведенные x и y rectQuickItem?
Я обнаружил, что item_x и item_y не являются x и y, которые на самом деле применяются в пользовательском интерфейсе. Кажется, что transform: Translate добавляет некоторые единицы к x и y из rect, чего я не получаю, когда запрашиваю rectQuickItem->x().

Проще говоря, мне нужно, чтобы -20 и -30 применялись к x и y в transform: Translate блоке rect_parent, который в конечном итоге применяется к rect

Цель:
я изменяю родителя элемента rectQuickItem, чтобы отобразить его в другом окне с теми же координатами x и y, что и у исходного родителя. Мне нужны единицы, которые были добавлены к x и y свойств rectQuickItem из-за того, что transform: Translate было установлено так, чтобы отображать rect визуально в том же месте, что и предыдущий родитель.

Дополнительный вопрос:
будет ли QQuickItem::MapToItem помочь мне здесь?


person TheWaterProgrammer    schedule 27.02.2018    source источник
comment
относительно какого Item ему нужно получить координаты rect_object? относительно окна, относительно экрана, относительно родительского элемента?   -  person eyllanesc    schedule 28.02.2018
comment
Мне нужно это относительно родительского элемента, который rect_parent. В этой заметке, есть ли способ получить координаты относительно окна (main_window), то есть?   -  person TheWaterProgrammer    schedule 28.02.2018
comment
rect_parent является прямым родителем rect. Если вы увидите пример кода, вы поймете, что я имею в виду. Я имею в виду QQuickItems по их идентификаторам в QML.   -  person TheWaterProgrammer    schedule 28.02.2018
comment
@eyllanesc Я предоставил информацию, которую вы искали? Мои знания о том, что делает блок transform: Translate, очень базовые. следовательно, мой вопрос тоже может быть отбит :-)   -  person TheWaterProgrammer    schedule 28.02.2018
comment
Если вы переходите с C++ на QML, вы уже находитесь в стране плохих практик проектирования программного обеспечения.   -  person dtech    schedule 28.02.2018
comment
@dtech Я делаю довольно сложную вещь, когда некоторые QQuickItem, отображаемые на экране, должны визуально отображаться за пределами экрана с теми же координатами, что и на экране. То, как я это делаю сейчас, заключается в том, что я создаю базу QQuickItem на стороне C++, которая имеет те же размеры, что и экранное окно. Затем я выбираю QQuickItems на экране, которые должны быть отображены за пределами экрана, и устанавливаю их родителя как окно за пределами экрана, а затем вызываю обновление в окне за пределами экрана. Это, безусловно, требует обработки C++. Следовательно, необходимо иметь дело с элементами QML на стороне C++.   -  person TheWaterProgrammer    schedule 28.02.2018
comment
Вы можете превратить это в интерфейс, к которому подключается QML, и, таким образом, избежать доступа к QML из C++. Это правильный путь. Необходимость полагаться на поиск объектов по имени объекта... на самом деле это не тот подход, который следует использовать в производственном коде.   -  person dtech    schedule 28.02.2018
comment
@dtech Я заинтересован в том, чтобы улучшить мой код. есть ли конкретный пример, который показывает, как получить указатель QQuickItem на элемент QML, не обязательно имея дело с именем объекта. Я думаю, что я должен поднять отдельный вопрос по этому поводу для всеобщего блага.   -  person TheWaterProgrammer    schedule 28.02.2018
comment
Идея заключалась в том, что вы должны облегчить функциональность на стороне C++ полностью независимо от любого графического интерфейса. Никакого прикосновения к объектам qml. Но поскольку все это связано с графическим интерфейсом, возникает большой вопрос, зачем вообще нужен C++? Звучит так, будто это можно и нужно делать полностью в qml.   -  person dtech    schedule 28.02.2018


Ответы (1)


Если вы хотите получить координаты элемента относительно другого элемента, процедура такова:

  • преобразовать положение элемента в положение относительно сцены
  • преобразовать позицию по отношению к сцене в позицию по отношению к другому элементу.

static QPointF positionToAnotherItem(QQuickItem *source, QQuickItem *destine){
    QPointF p = source->mapToScene(QPointF(0, 0));
    return destine->mapFromScene(p);
}

static QPointF positionToParent(QQuickItem *item){
    return positionToAnotherItem(item, item->parentItem());
}

преобразования не применяются сразу, поэтому, применяя описанную выше процедуру, вы не получите правильных позиций, вы должны применять их с помощью сигналов xChanged и YChanged.

QQuickItem *rectQuickItem = qml_engine.rootObjects()[0]->findChild<QQuickItem*>("rect_object");
//QQuickItem *rectQuickItemParent = qml_engine.rootObjects()[0]->findChild<QQuickItem*>("rect_parent_object");

QObject::connect(rectQuickItem, &QQuickItem::xChanged, [rectQuickItem]{
    qDebug()<<positionToParent(rectQuickItem);
});

QObject::connect(rectQuickItem, &QQuickItem::yChanged, [rectQuickItem]{
    qDebug()<<positionToParent(rectQuickItem);
});

В следующей ссылке приведен полный пример

person eyllanesc    schedule 27.02.2018
comment
Просто чтобы вы знали, я делаю rectQuickItem->setParentItem(new_parent_window), когда рисую его в новом окне/QQuickItem. Но независимо от этого ваш ответ объясняет способ получить QPointF от одного родителя и сопоставить с другим родителем. Похоже, это то, что мне нужно сделать - person TheWaterProgrammer; 28.02.2018
comment
Позвольте мне правильно понять и попробовать это. - person TheWaterProgrammer; 28.02.2018