当我们需要定义自己的类时候,可以重定义itemChange函数。如果需要item状态发生改变时发送通知,需要开启对应的功能。在构造函数当中引用setFlag(ItemSendsGeometryChanges);
设置ItemSendsGeometryChange标志位。
Node::Node()
{
setFlag(ItemIsMovable); //提供拖拽功能
setFlag(ItemSendsGeometryChanges); //打开通知
//setCacheMode(DeviceCoordinateCache);
//setZValue(-1);
}
关于setFlag函数的说明可参照【Qt系列】Graphics View框架下实现自定义item类的拖动,在自定义Item类的声明重定义函数itemChange函数,直接复制粘贴就好。
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
如代码所示,该函数有两个输入参数,一个是GraphicsItemChange,一个是QVariant。
GraphicsItemChange
这是QGraphicsItem类的枚举。此枚举描述了 QGraphicsItem::itemChange() 通知的状态更改。通知在状态更改时发送,在某些情况下,可以进行调整(有关详细信息,请参阅每个更改的文档)。
注意:在 itemChange() 中调用 QGraphicsItem 本身的函数时要小心,因为某些函数调用可能会导致不需要的递归。例如,您不能在 ItemPositionChange 通知时调用 itemChange() 中的 setPos(),因为 setPos() 函数将再次调用 itemChange(ItemPositionChange)。相反,您可以从 itemChange() 返回新的、调整后的位置。
以下为该枚举的取值。
常量 | 描述 |
---|---|
QGraphicsItem::ItemEnabledChange | 项目的启用状态发生更改。如果该项目当前处于启用状态,它将被禁用,反之亦然。值参数是新启用的状态(即 true 或 false)。不要在 itemChange() 中调用 setEnabled(),因为此通知已传递。相反,您可以从 itemChange() 返回新状态。 |
QGraphicsItem::ItemEnabledHasChanged | 项目的启用状态已更改。值参数是新启用的状态(即 true 或 false)。不要在 itemChange() 中调用 setEnabled(),因为此通知已传递。返回值将被忽略。 |
QGraphicsItem::ItemMatrixChange | 项目的仿射转换矩阵正在更改。此值已过时;您可以改用 ItemTransformChange。 |
QGraphicsItem::ItemPositionChange | 项目的位置发生变化。如果启用了 ItemSendsGeometryChanges 标志,并且当项目的本地位置相对于其父级(即,由于调用 setPos() 或 moveBy())而发生更改时,将发送此通知。值参数是新位置(即 QPointF)。您可以调用 pos() 来获取原始位置。不要在 itemChange() 中调用 setPos() 或 moveBy() 作为此通知的传递;相反,您可以从 itemChange() 返回新的、调整后的位置。在此通知之后,如果位置发生更改,QGraphicsItem 会立即发送 ItemPosition 已更改通知。 |
QGraphicsItem::ItemPositionHasChanged | 项目的位置已更改。如果启用了 ItemSendsGeometryChanges 标志,并且在项目的本地位置(相对于其父级)发生更改后,将发送此通知。value 参数是新位置(与 pos() 相同),QGraphicsItem 忽略此通知的返回值(即只读通知)。 |
QGraphicsItem::ItemTransformChange | 项目的转换矩阵将发生更改。如果启用了 ItemSendsGeometryChanges 标志,并且当项目的本地转换矩阵发生更改(即,作为调用 setTransform() 的结果)时,将发送此通知。值参数是新矩阵(即 QTransform);要获取旧矩阵,请调用 transform()。在传递此通知时,不要调用 setTransform() 或在 itemChange() 中设置任何转换属性;相反,您可以从 itemChange() 返回新矩阵。如果更改转换属性,则不会发送此通知。 |
QGraphicsItem::ItemTransformHasChanged | 项的转换矩阵已更改,因为调用了 setTransform,或者更改了其中一个转换属性。如果启用了 ItemSendsGeometryChanges 标志,并且在项目的本地转换矩阵发生更改后,将发送此通知。value 参数是新矩阵(与 transform() 相同),QGraphicsItem 忽略此通知的返回值(即只读通知)。 |
QGraphicsItem::ItemRotationChange | 项的旋转属性将发生更改。如果启用了 ItemSendsGeometryChanges 标志,并且当项目的旋转属性发生更改(即,作为调用 setRotation() 的结果)时,将发送此通知。值参数是新的旋转(即双精度);要获取旧的旋转,请调用 rotation()。不要在 itemChange() 中调用 setRotation() 作为此通知的传递;相反,您可以从 itemChange() 返回新的旋转。 |
QGraphicsItem::ItemRotationHasChanged | 项的旋转属性已更改。如果启用了 ItemSendsGeometryChanges 标志,并且在项目的旋转属性发生更改后,将发送此通知。value 参数是新的旋转(即双精度),QGraphicsItem 忽略此通知的返回值(即只读通知)。不要在 itemChange() 中调用 setRotation(),因为此通知已传递。 |
QGraphicsItem::ItemScaleChange | 项目的比例属性将发生更改。如果启用了 ItemSendsGeometryChanges 标志,并且当项目的 scale 属性发生更改(即,作为调用 setScale() 的结果),则会发送此通知。值参数是新刻度(即双精度);要获取旧的刻度,请调用 scale()。不要在 itemChange() 中调用 setScale(),因为此通知已送达;相反,您可以从 itemChange() 返回新比例。 |
QGraphicsItem::ItemScaleHasChanged | 项目的比例属性已更改。如果启用了 ItemSendsGeometryChanges 标志,并且在项目的 scale 属性发生更改后,将发送此通知。value 参数是新刻度(即双精度),QGraphicsItem 忽略此通知的返回值(即只读通知)。不要在 itemChange() 中调用 setScale(), 因为此通知已传递。 |
QGraphicsItem::ItemTransformOriginPointChange | 项的变换原点属性发生更改。如果启用了 ItemSendsGeometryChanges 标志,并且当项目的转换源点属性发生更改(即,作为调用 setTransformOriginPoint() 的结果),则会发送此通知。值参数是新的原点(即 QPointF);若要获取旧的原点,请调用 transformOriginPoint()。不要在 itemChange() 中调用 setTransformOriginPoint() 作为此通知的传递;相反,您可以从 itemChange() 返回新的转换原点。 |
QGraphicsItem::ItemTransformOriginPointHasChanged | 项的变换原点属性已更改。如果启用了 ItemSendsGeometryChanges 标志,并且在项目的转换源点属性发生更改后,将发送此通知。value 参数是新的源点(即 QPointF),QGraphicsItem 忽略此通知的返回值(即只读通知)。不要在传递此通知时在 itemChange() 中调用 setTransformOriginPoint()。 |
QGraphicsItem::ItemSelectedChange | 项目的选定状态将发生更改。如果当前选择了该项目,它将变为未选中状态,反之亦然。值参数是新选定的状态(即 true 或 false)。不要在 itemChange() 中调用 setSelected()作为此通知的传递;相反,您可以从 itemChange() 返回新的选定状态。 |
QGraphicsItem::ItemSelectedHasChanged | 项目的选定状态已更改。值参数是新选定的状态(即 true 或 false)。不要在 itemChange() 中调用 setSelected(),因为此通知已传递。返回值将被忽略。 |
QGraphicsItem::ItemVisibleChange | 项目的可见状态发生更改。如果该项目目前可见,它将变得不可见,反之亦然。值参数是新的可见状态(即,真或假)。不要在 itemChange() 中调用 setVisible(),因为此通知已送达;相反,您可以从 itemChange() 返回新的可见状态。 |
QGraphicsItem::ItemVisibleHasChanged | 项目的可见状态已更改。值参数是新的可见状态(即,真或假)。不要在 itemChange() 中调用 setVisible(),因为此通知已传递。返回值将被忽略。 |
QGraphicsItem::ItemParentChange | 项目的父项将发生更改。值参数是新的父项(即 QGraphicsItem 指针)。不要在 itemChange() 中调用 setParentItem() 作为此通知的传递;相反,您可以从 itemChange() 返回新的父级。 |
QGraphicsItem::ItemParentHasChanged | 项目的父项已更改。值参数是新的父级(即指向 QGraphicsItem 的指针)。不要在 itemChange() 中调用 setParentItem() 作为此通知的传递。返回值将被忽略。 |
QGraphicsItem::ItemChildAddedChange | 一个孩子将添加到此项目中。值参数是新的子项(即 QGraphicsItem 指针)。在传递此通知时,不要将此项目传递给任何项目的 setParentItem() 函数。返回值未使用;您无法调整此通知中的任何内容。请注意,发送此通知时,新子项可能未完全构造;在子项上调用纯虚拟函数可能会导致崩溃。 |
QGraphicsItem::ItemChildRemovedChange | 将从此项目中删除一个孩子。值参数是要删除的子项(即 QGraphicsItem 指针)。返回值未使用;您无法调整此通知中的任何内容。 |
QGraphicsItem::ItemSceneChange | 项目将移动到新场景。当项目添加到其初始场景以及移除项目时,也会发送此通知。项目的 scene() 是旧场景(如果项目尚未添加到场景中,则为 0)。值参数是新场景(即 QGraphicsScene 指针),如果从场景中删除了该项目,则为空指针。不要通过将此项目传递给 QGraphicsScene::addItem() 来覆盖此更改,因为此通知已送达;相反,您可以从 itemChange() 返回新场景。请谨慎使用此功能;反对场景更改可能会很快导致不必要的递归。 |
QGraphicsItem::ItemSceneHasChanged | 项目的场景已更改。项目的 scene() 是新场景。当项目添加到其初始场景以及移除项目时,也会发送此通知。值参数是新场景(即指向 QGraphicsScene 的指针)。不要在 itemChange() 中调用 setScene(),因为此通知已传递。返回值将被忽略。 |
QGraphicsItem::ItemCursorChange | 项目的光标将发生更改。值参数是新游标(即 QCursor)。不要在 itemChange() 中调用 setCursor(),因为此通知已传递。相反,您可以从 itemChange() 返回新的游标。 |
QGraphicsItem::ItemCursorHasChanged | 项目的光标已更改。值参数是新游标(即 QCursor)。不要调用 setCursor(),因为此通知已传递。返回值将被忽略。 |
QGraphicsItem::ItemToolTipChange | 项目的工具提示会更改。值参数是新的工具提示(即 QToolTip)。不要在 itemChange() 中调用 setToolTip(),因为此通知已传递。相反,您可以从 itemChange() 返回新的工具提示。 |
QGraphicsItem::ItemToolTipHasChanged | 项目的工具提示已更改。值参数是新的工具提示(即 QToolTip)。不要调用 setToolTip(),因为此通知已传递。返回值将被忽略。 |
QGraphicsItem::ItemFlagsChange | 项目的标志会更改。值参数是新标志(即 quint32)。不要在 itemChange() 中调用 setFlags(),因为此通知已传递。相反,您可以从 itemChange() 返回新标志。 |
QGraphicsItem::ItemFlagsHaveChanged | 项目的标志已更改。值参数是新标志(即 quint32)。不要在 itemChange() 中调用 setFlags(),因为此通知已传递。返回值将被忽略。 |
QGraphicsItem::ItemZValueChange | 项目的 Z 值将发生更改。值参数是新的 Z 值(即双精度值)。不要在 itemChange() 中调用 setZValue(),因为此通知已传递。相反,您可以从 itemChange() 返回新的 Z 值。 |
QGraphicsItem::ItemZValueHasChanged | 项目的 Z 值已更改。值参数是新的 Z 值(即双精度值)。不要在传递此通知时调用 setZValue()。返回值将被忽略。 |
QGraphicsItem::ItemOpacityChange | 项目的不透明度将发生更改。值参数是新的不透明度(即双精度)。不要在传递此通知时在 itemChange() 中调用 setOpacity()。相反,您可以从 itemChange() 返回新的不透明度。 |
QGraphicsItem::ItemOpacityHasChanged | 项目的不透明度已更改。值参数是新的不透明度(即双精度)。不要调用 setOpacity(),因为此通知已传递。返回值将被忽略。 |
QGraphicsItem::ItemScenePositionHasChanged | 项目的场景位置已更改。如果启用了 ItemSendsScenePositionChanges 标志,并且在项目的场景位置已更改(即,项目本身的位置或变换或任何祖先的位置或变换已更改)之后,将发送此通知。值参数是新的场景位置(与 scenePos() 相同),QGraphicsItem 忽略此通知的返回值(即只读通知)。 |
举例
以位置改变后发出通知举例,在构造函数通过setFlag(ItemSendsGeometryChanges);
打开通知功能。
QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
{
switch (change) {
case ItemPositionChange:
qDebug()<<"位置将发生变化";
break;
case ItemPositionHasChanged:
qDebug()<<"位置发生了变化";
break;
default:
break;
};
return QGraphicsItem::itemChange(change, value);
}
演示效果如下:
当item状态发生改变时,会自动调用itemChange函数,利用switch case来判断item改变的通知类型,一种叫ItemPositionChange,一种叫ItemPositionHasChanged,通过Debug也能看出,一次移动会发出两次通知。从字面意思看,这两个通知一个叫【将要移动】,一个叫【已经移动】。
仔细阅读上述说明文档,能看出两者区别。
- 接收到ItemPositionChange后,value这个值是新位置,通过调用pos可以获取原始位置,即未移动前的位置,而且会return新的位置。
- 接收到ItemPositionHasChange后,value这个值也是新位置,但是调用pos获取的也是新位置,原始位置不能获取了,而且并不会return新的位置,只是个只读通知。