c++ - 如何防止子 QGraphicsItem 与父级一起移动?

标签 c++ qt qgraphicsview qgraphicsitem

我有一个 GraphicsBoxItem ,其中包含 GraphicsImageItem 列表(框周围的某种 float 按钮)。我在 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();
};

最佳答案

子级的位置始终相对于其父级,如果父级移动,则子级的绝对位置也会发生变化。

如果您想制造这种情况不会发生的错觉,则必须手动将子项向相反方向移动,以便它可以保持在相同的绝对位置。

另一种选择是首先不将这些项目作为子项。

也许您应该创建一个不可见的项目,然后将可移动项目及其不可移动子项目作为其父级,并将可移动子项目设置为可移动项目的父级。然后,您只需移动可移动的项目 - 它的子项目移动,其兄弟项目保持在相同位置,因为它们的父项目不移动。

关于c++ - 如何防止子 QGraphicsItem 与父级一起移动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49239168/

相关文章:

c++ - 英特尔 MKL 内存管理和异常

c++ - 设置文件指针位置

c++ - 根据 QComboBox 的选择更改 QTableView 中的数据

项目中的 C++ 全局常量

qt - 如何显示 QGraphicsPixmapItem 中的像素位置和颜色

c++ - 在 openGL 中旋转 View ?

c++ - 通过别名定义前向定义的 C++ 结构

c++ - Qt资源国际化失败

c++ - 缩放 QGraphicsView 而不缩放已添加到其中的 QWidget

qt - 根据缩放级别渲染 QGraphicsScene