如何防止子QGraphicsItem与父移动?

时间:2018-03-12 15:41:25

标签: c++ qt qgraphicsview 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();
};

3 个答案:

答案 0 :(得分:4)

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

如果你想创造一种不会发生这种情况的错觉,你必须手动移动孩子,使其保持相同的绝对位置。

另一种选择是首先不要将这些物品作为儿童。

也许你应该创建一个不可见的项目,然后将可移动项目以及不可移动的子项和可移动子项置于可移动项目之下。然后你只需移动可移动物品 - 它的孩子移动,其兄弟姐妹保持在同一位置,因为他们的父母不会移动。

答案 1 :(得分:0)

对于您不想移动的子项,请尝试设置此标记:

 <div ng-repeat="x in processes">
<input type="checkbox" ng-model="filteredData"/>{{x}}
</div>
<div ng-repeat = "y in toBeFiltered | filter: {filteredData : true}">
<span class="title">{{y.Title}}</span>
<span class="process"> {{y.process}}</span>
</div>

<script>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
  $scope.processes = [
    "Alfreds Futterkiste",
    "Berglunds snabbköp",
    "Centro comercial Moctezuma",
    "Ernst Handel",
  ];
  $scope.toBeFiltered = [{
  "Title": "title1",
  "process": ["Alfreds Futterkiste"]
  }, {"Title" : "title2",
  "process": ["Alfreds Futterkiste, Berglunds Snabbkop"]

  },{"Title" : "title2",
  "process": ["Alfreds Futterkiste, Berglunds Snabbkop,Ernst Handel, 
  Centro Comercial Moctezuma"]
  }];
});
</script>

答案 2 :(得分:0)

如果可以子类化子项,则可以覆盖itemChange()方法并注意:

ItemScenePositionHasChanged

  

该项目的场景位置已更改。该通知在以下情况下发送   在启用ItemSendsScenePositionChanges标志后,   项目的场景位置已更改(即,位置或   项目本身的变换或位置或变换   任何祖先已更改)。 value参数是新场景   位置(与scenePos()相同),并且QGraphicsItem忽略   此通知的返回值(即只读通知)。

然后返回子项的最后一个ScenePos(),您必须将其存储为成员并更新每个场景位置更改。

记住要设置标志:

ItemSendsGeometryChanges

在您的孩子子类的ctor中。