QGraphicsItem【详细描述】

 

这个类为编写用户的定制项目提供了一个轻量级的基础,包括定义项目的几何图形、碰撞检测和绘画以及通过事件处理进行的项目交互。QGraphicsItem是 Graphics View Framework 的一部分。


Qt为常见的形状提供了如下标准图形项。

QGraphicsEllipseItem

提供椭圆项

QGraphicsLineItem

提供一个行项

QGraphicsPathItem

提供任意路径项

QGraphicsPixmapItem

提供一个位图项

QGraphicsRectItem

提供多边形项

QGraphicsRectItem

提供一个矩形项

QGraphicsSimpleTextItem

提供简单的文本标签项

QGraphicsTextItem

提供高级文本浏览器项

项目的所有几何信息都基于其局部坐标系。项目的位置 pos()是唯一不在本地坐标中操作的函数,因为它返回父坐标中的位置。  The Graphics View Coordinate System 详细描述QT坐标系。

您可以通过调用来  setVisible()设置某项是否可见(即绘制和接受事件),setVisible() 隐藏项目的同时也将隐藏其子项目。同样,您可以通过调用setEnabled(),如果禁用某个项目,其所有子项目也将被禁用。默认情况下,项目既是可见的又是启用的。若要切换某项是否被选中,首先通过设置  ItemIsSelectable 标志,然后调用  setSelected()。通常,用户交互的结果是场景切换选择。


要编写自己的图形项,首先要创建QGraphicsItem的子类,然后从实现它的两个纯虚拟公共函数开始:boundingRect(),它返回项目绘制区域的估计值,以及  paint(),它实现了实际的绘画。例如:

class SimpleItem : public QGraphicsItem //创建用户的图形项派生类
{
public:

    //QRectF类使用浮点精度在平面中定义一个有限矩形。
    //重新实现虚函数,为图形项外部定义一个矩形边界,所有绘画限制于框中
    QRectF boundingRect() const override  
    {
        //qreal其实就是double;在嵌入设备系统则等同于float。
        qreal penWidth = 1;

        return QRectF(-10 - penWidth / 2, -10 - penWidth / 2,
                      20 + penWidth, 20 + penWidth);
    }


    //重新实现虚函数,以局部坐标绘制项的内容。
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
               QWidget *widget) override
    {
        //画一个圆角矩形
        painter->drawRoundedRect(-10, -10, 20, 20, 5, 5);
    }
};

boundingRect() 函数有许多不同的用途。QGraphicsScene其项目索引基于boundingRect(),QGraphicsView使用它来剔除不可见的项目,并在绘制重叠项目时确定需要重新构图的区域。

此外,QGraphicsItem的冲突检测机制使用boundingRect()提供有效的截止。碰撞检测 collidesWithItem()中的细粒度碰撞算法是基于调用 shape(),它返回项目形状的准确轮廓作为QPainterPath

QGraphicsScene期望所有项目的boundingRect()和 shape()保持不变。如果要以任何方式更改项的几何形状,必须首先调用 prepareGeometryChange() ,以允许QGraphicsScene来更新它的簿记。


 碰撞检测可以通过两种方式进行:

1.重新实现shape() 为您的项目返回一个准确的形状,并依赖于collidesWithItem() 进行“形状-形状”相交。如果形状很复杂,这可能是相当“昂贵”的。
2.重新实现 collidesWithItem() ,以提供您自己自定义的项目和形状碰撞算法。


可以调用 contains() 函数来确定该项是否包含一个点。这个功能也可以通过项目重新实现。contains() 的默认行为是基于调用 shape()的。

项目可以包含其他项目,也可以由其他项目包含。所有项目都可以有一个父项和一个子项列表。除非项目没有父坐标,否则其位置在父坐标中(即[]e。,父坐标的局部坐标)。父项将它们的位置和转换传播到所有子项。

项目可以包含其他项目,也可以被其他项目包含。所有项目都可以有一个父项目和一个子项目列表。除非该项没有父项,否则它的位置在父坐标中(即父节点的本地坐标)。父项目将它们的位置和变换传播给所有子项目。


 转换 

除了基本位置之外,QGraphicsItem还支持投影变换,刷卡机pos() 有几种方法可以更改项目的变换。对于简单的转换,您可以调用其中一个便利函数setRotation()或setScale(),或者您可以将任何转换矩阵传递给setTransform(),对于高级转换控制,您还可以选择通过调用setTransformations()。

项变换从父项到子项累积,因此如果父项和子项都旋转90度,子项的总变换将为180度。同样,如果该项的父项缩放到其原始大小的两倍,则其子项也将是原来的两倍。项目的变换不影响其自身的局部几何形状;所有几何函数(例如:包含包含 contains(), update() 和所有映射函数)仍然在本地坐标中操作。为了方便起见,QGraphicsItem提供了函数场景转换sceneTransform(),它返回该项的总变换矩阵(包括其位置以及所有父项的位置和变换),以及 scenePos(),它返回其在场景坐标中的位置。若要重置项目的矩阵,请调用resetTransform()。

根据应用的顺序,某些转换操作会产生不同的结果。例如,如果缩放一个变换,然后旋转它,可能会得到与先旋转变换不同的结果。但是,您在QGraphicsItem上设置转换属性的顺序不会影响结果转换;QGraphicsItem始终以固定的定义顺序应用属性:


 绘画 

paintpaint() 函数调用QGraphicsView绘制项目的内容。该项目没有自己的背景或默认填充;项目后面的任何内容都将通过该函数中未明确绘制的所有区域发出。你可以通过update() 重画,可以选择传递需要重画的矩形。根据项目在视图中是否可见,项目可能会也可能不会被重新绘制;没有等同于QWidget::repaint() 。

项目由视图绘制,从父项目开始,然后按升序堆叠顺序绘制子项目。您可以通过调用来设置项的堆叠顺序setZValue(),并通过调用zValue(),具有低z值的项目在具有高z值的项目之前绘制。堆叠顺序适用于同级项目;父母总是比孩子先被引入。


 整理 

所有项目都以定义的稳定顺序绘制,该顺序决定了当您在场景中单击时哪些项目将首先接收鼠标输入。通常你不必担心排序问题,因为项目遵循“自然顺序”,遵循场景的逻辑结构。

项的子项堆叠在父项的顶部,同级项按插入顺序堆叠(即,按添加到场景中或添加到同一父项的相同顺序)。如果您先添加A项,然后添加B项,那么B项将位于A项之上。如果您随后添加C项,则这些项的堆叠顺序将是A项,B项,C项。

此示例显示了中机器人所有肢体的堆叠顺序(QT拖放机器人实例)举例。躯干是根项目(所有其他项目都是躯干的子项目或后代),因此首先绘制它。接下来,绘制头部,因为它是躯干子列表中的第一个项目。然后画左上手臂。由于下手臂是上臂的子手臂,因此将绘制下手臂,然后绘制上臂的下一个兄弟手臂,即上臂的右手臂,依此类推。

 对于高级用户,有多种方法可以改变项目的排序方式: 

  • 你可以通过setZValue() 将其显式堆叠在其他同级项的顶部或下方。项目的默认Z值为0。具有相同Z值的项目按插入顺序堆叠。
  • 你可以 stackBefore()对子列表重新排序。这将直接修改插入顺序。
  • 您可以设置ItemStacksBehindParent 将子项堆叠在其父项后面。

两个同级项目的堆叠顺序也影响每个项目各自的子项目。因此,如果一个项目在另一个项目之上,那么它的所有子项目也将在其他项目的所有子项目之上。


 事件 

QGraphicsItem 通过​​​​​​ sceneEvent()函数将常见事件分配给一组方便的事件处理程序:

您可以通过安装事件过滤器来过滤任何其他项的事件。该功能于Qt的常规事件过滤不同(参见QObject::installEventFilter()),它只作用于QObject的子类。通过调用installSceneEventFilter()将您的项安装为另一个项的事件过滤器,过滤后的事件将由虚函数sceneEventFilter()接收,您可以通过调用removeSceneEventFilter()来移除项目事件过滤器。


 自定义数据 

有时,向项目注册自定义数据很有用,无论是自定义项还是标准项。你可以调用 setData() 来使用键-值对(键是整数,值是QVariant)在其中存储数据。若要从项中获取自定义数据,请调用 data(),Qt本身完全没有触及这一功能,它是专为了方便用户提供的。

See also QGraphicsSceneQGraphicsView, and Graphics View Framework.


<<<返回上一级页面【QGraphicsItem类】

<<<返回根页面

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值