Как предотвратить перемещение дочернего QGraphicsItem вместе с родителем?

У меня есть GraphicsBoxItem, который содержит список GraphicsImageItem (какие-то плавающие кнопки вокруг коробки). Я создаю их на лету в focusInEvent() и уничтожаю в focusOutEvent(). Некоторые из GraphicsImageItem должны перемещаться вместе с родителем при щелчке, некоторые из них должны оставаться на том же месте при щелчке, пока поле не получит focusOut, щелкнув за пределами любых графических элементов. Есть ли способ предотвратить перемещение дочернего QGraphicsItem вместе с родительским?

class GraphicsBoxItem : public QObject, public QGraphicsItem
{
    Q_OBJECT
private:
    QColor mColor;
    QVector<GraphicsImageItem*> mItemList;
public:
    GraphicsBoxItem(QGraphicsItem *parent = NULL)
        :QGraphicsItem(parent)
    {
        mColor = Qt::lightGray;
        setFlag(QGraphicsItem::ItemIsSelectable);
        setFlag(QGraphicsItem::ItemIsFocusable);
    }

    QRectF boundingRect() const { return QRectF(50, 20, 100, 60); }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        painter->setBrush(mColor);
        painter->drawRect(boundingRect());
    }
    virtual void focusOutEvent(QFocusEvent * event)
    {
        foreach(GraphicsImageItem *item1, mItemList)
        {
            item1->deleteLater();
            item1 = NULL;
        }
        mItemList.clear();
        mColor = Qt::lightGray;
        QGraphicsItem::focusOutEvent(event);
    }

    virtual void focusInEvent(QFocusEvent * event)
    {
        GraphicsImageItem *movableItem = new GraphicsImageItem(this);
        movableItem->setPos(150, 20);
        mItemList.push_back(movableItem);
        movableItem->installSceneEventFilter(this);
        connect(movableItem, SIGNAL(SignalClicked()), this, SLOT(SlotButtonClicked()));

        GraphicsImageItem *nonMovableItem = new GraphicsImageItem(this);
        nonMovableItem->setPos(20, 20);
        mItemList.push_back(nonMovableItem);
        nonMovableItem->installSceneEventFilter(this);
        connect(nonMovableItem, SIGNAL(SignalClicked()), this, SLOT(SlotButtonClicked()));

        mColor = Qt::blue;
        QGraphicsItem::focusInEvent(event);
    }

    bool sceneEventFilter(QGraphicsItem* target, QEvent* event)
    {
        if (event->type() == QEvent::GraphicsSceneMousePress || event->type() == QEvent::GraphicsSceneMouseDoubleClick)
        {
            GraphicsImageItem* item = dynamic_cast<GraphicsImageItem*>(target);
            if (item)
            {
                item->SignalClicked();
                qDebug() << "image button was clicked: Need to set the focus back to the box";
                setFocus();
                return true;
            }
        }
        return QGraphicsItem::sceneEventFilter(target, event);
    }
public slots:

    void SlotButtonClicked()
    {
        setPos(pos().x() + 10, pos().y()+10);
    }
};

SignalClicked() перемещает GraphicsBoxItem на 10 пикселей. Некоторые из GraphicsImageItem остаются на месте, некоторые перемещаются с GraphicsBoxItem:

class GraphicsImageItem : public QGraphicsSvgItem
{
    Q_OBJECT
public:
    GraphicsImageItem::GraphicsImageItem(QGraphicsItem *parent = NULL)
    : QGraphicsSvgItem(QString(":/images/icon.svg"), parent)
    {
        setFlag(QGraphicsItem::ItemIsSelectable);
    }

    QRectF boundingRect() const { return QRectF(0, 0, 30, 30); }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        painter->setBrush(Qt::lightGray);
        painter->drawRect(boundingRect());
        renderer()->render(painter, boundingRect().adjusted(3, 3, -3, -3));
    }

Q_SIGNALS:
    void SignalClicked();
};
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
983
3

Ответы 3

Положение дочернего элемента всегда относительно его родителя, если родитель перемещается, то абсолютное положение дочернего элемента также изменяется.

Если вы хотите создать иллюзию того, что этого не происходит, вам придется вручную переместить ребенка в противоположном направлении, чтобы он мог оставаться в том же абсолютном положении.

Другой вариант - вообще не иметь элементы как дочерние элементы.

Может быть, вам следует создать невидимый элемент, а затем сделать его родительским для подвижного объекта, а также для его неподвижных дочерних элементов, а для подвижных дочерних элементов - для этого подвижного объекта. Затем вы просто перемещаете только подвижный элемент - его дочерние элементы перемещаются, его братья и сестры остаются в том же положении, поскольку их родительский элемент не перемещается.

Я пробовал подход с использованием другого родителя для подвижных элементов. Однако этот подход не сработал, потому что я воссоздаю все элементы в focusIn(). Внутри этой функции я не могу знать, попал ли я туда из-за щелчка по кнопке (кнопка должна оставаться в том же положении) или из-за того, что я щелкнул вне каких-либо элементов. После следующего щелчка по окну мне нужно будет разместить неподвижную кнопку рядом с окном. Есть ли способ запретить ящику получать событие focusOut () при нажатии кнопки GraphicsImageItem?

user2246120 12.03.2018 18:31

@ user2246120 Inside that function I can't know Да, вы можете, просто передайте параметр, чтобы указать источник.

dtech 12.03.2018 20:47

Я имел в виду focusInEvent(QFocusEvent*) от Qt. Изначально неподвижный элемент находится в верхнем левом углу поля, когда он получает фокус. Затем предмет остается, пока ящик перемещается. при нажатии за пределами сцены и повторном выборе поля неподвижный элемент теперь снова должен быть помещен рядом с ящиком. Если вы не потеряете фокус при щелчке по неподвижному объекту, это решит проблему ... Возможно ли это?

user2246120 13.03.2018 21:46

Для дочерних элементов, которые вы не хотите перемещать, попробуйте установить этот флаг:

setFlag(QGraphicsItem::ItemIgnoresTransformations);

Похоже, в данном случае это не работает. В документации сказано: «его позиция по-прежнему привязана к своему родителю» ...

user2246120 13.03.2018 21:48

Если вы можете создать подкласс своих дочерних элементов, вы можете переопределить метод itemChange () и следить за:

ItemScenePositionHasChanged

The item's scene position has changed. This notification is sent if the ItemSendsScenePositionChanges flag is enabled, and after the item's scene position has changed (i.e., the position or transformation of the item itself or the position or transformation of any ancestor has changed). The value argument is the new scene position (the same as scenePos()), and QGraphicsItem ignores the return value for this notification (i.e., a read-only notification).

Затем верните последний scenePos () дочернего элемента, который вам нужно будет сохранить как член, и обновите каждое изменение положения сцены.

Не забудьте установить флаг:

ItemSendsGeometryChanges

в ctor вашего дочернего подкласса.

Другие вопросы по теме