当视图中的复杂图元比较多的时候,图形框架应用的性能会下降很多。这时候,我们就需要对默认的渲染策略进行调整从而提升用户体验。图形视图框架的优化方向主要分为以下几种:
1.调整图元的二叉树结构
2.对图元的绘制函数进行缓存
3.优化视图渲染
4.采用OpenGL进行渲染
下面分别介绍一下几种优化策略
调整图元二叉树
在图元视图框架内部,各个Item的位置采用二叉树数据结构来进行存储。这种数据结构的优势是是查询比较快,也就是通过items()或者itemAt()来定位查找图元的时候会比较快,这对于图元的碰撞检测也是很有帮助的。但是这种数据结构也有问题,就是如果移动了一个图元,那么框架就需要更新整个二叉树,如果图元比较多的时候这个更新操作是很耗时的。
如果图元比较多,且你不需要图元的位置信息二叉树的时候,可以通过下面的函数来禁用索引信息,从而提升视图的渲染性能。
scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
没有位置信息二叉树的时候,调用items()或者itemAt()查找元素的时候,就需要遍历所有的元素进行查找,如果图元比较多的话,查找也会引发性能问题。所以这个配置要根据自己项目的具体场景选择是否开启。
如果无法完全放弃二叉树索引,我们也可以通过setBspTreeDepth()修改二叉树的深度来优化性能,不过这个参数设置也要和具体场景结合起来。
绘制缓存
如果某个图元的绘制函数是很耗时的,我们可以开启该图元的缓存模式来进行优化,默认的情况,缓存模式是被关闭的。缓存模式开启的函数如下:
//@1缓存模式
//@2逻辑换存的大小
void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize = QSize())
常见的缓存模式如下表所示:
模式 | 说明 |
---|---|
NoCache | 默认缓存模式被禁用,每次图元需要重绘的时候 QGraphicsItem::paint()函数都会被调用。 |
ItemCoordinateCache | 给图元指定一个QSize()大小的缓存,缓存里面的图像可以用来进行后续的绘制和位移变换。如果想调整缓存图像的质量和分辨率,可以通过调用setCacheMode()分配一块更大的空间。 |
DeviceCoordinateCache | 绘制设备级别的缓存优化,主要适用于那些可以移动,但不会发生位移变化(旋转、缩放、剪切)的图元。如果图元发生了位移变化,那么缓存会自动更新。和ItemCoordinateCache不同 DeviceCoordinateCache不需要指定缓存空间大小,它始终以最高质量进行渲染。 |
视图优化
默认的情况下QGraphicsView在绘制背景和图元的时候会保护pianter的绘制状态。如果我们通过setPen()或者setBrush()修改了绘制状态,该状态会被一直保持,如果图元比较多的时候该绘制状态保持操作是比较耗时的,View中每个图元都需要执行对应的操作。我们可以通过下面的配置来禁用这种配置:
setOptimizationFlag(DontSavePainterState, true);
在禁用了自动绘制状态保持之后,我们就需要负责对painter()的状态进行控制了。禁用了自动绘制状态保持之后,标准控件也会影响painter()的状态。因此,如果同时使用标准图元和自定义图元,保持默认行为或设置 DontSavePainterState之后,在每次paint()绘制完毕的时候都需要将画笔和画刷恢复默认值。
默认情况下如果图元开启了抗锯齿操作,渲染的时候由于差值的影响很可能渲染的范围就超出了图元的边界,这就导致了渲染范围增大,从而影响了渲染性能。我们可以通过下面的配置来禁用边界以外的渲染行为:
setOptimizationFlag(DontAdjustForAntialiasing, true);
启用了该配置之后,抗锯齿渲染便不再渲染边界以外的图形,从而提升渲染性能。这个配置的副作用就是,以抗锯齿的模式绘制的图元在移动时候,会在Scene上留下绘制轨迹。
除了上面的配置之外,还可以通过指定QGraphicsView的渲染更新范围来优化图形框架的性能。对应的配置接口如下:
setViewportUpdateMode(ViewportUpdateMode mode);
更新模式分为五种分别如下:
模式 | 说明 |
---|---|
FullViewportUpdate | 更新整个viewport中的图元 |
MinimalViewportUpdate | 只更新需要更新的图元 |
SmartViewportUpdate | QGraphicsView会寻找最优的更新模式 |
BoundingRectViewportUpdate | Qt检测需要重绘的区域,然后在viewport上寻找一个矩形范围,将所有需要重绘的区域包含进去,对找到的矩形范围进行更新。 |
NoViewportUpdate | 当场景改变时, QGraphicsView永远不会更新它的视口,用户控制所有更新。 |
如果图元比较多,找需要更新的图元的时间大于更新整个viewport更新的时间,我们可以选择FullViewportUpdate模式,相反如果找需要更新的图元的时间小于更新整个viewport的时间,我们可以选择MinimalViewportUpdate模式。
OpenGL渲染优化
QGraphicsView默认的viewport是基于QWidget的性能受限制,我们可以通过使用
OpenGL widget替代QWidget来提升渲染性能。对应的配置如下:
QGraphicsView view;
view.setViewport(new QOpenGLWidget());
通常配置OpenGL替代QWidget能提升渲染性能,但Qt的图形视图框架并不是针对GPU设计的,并不能充分发挥GPU的性能。如果想使用可以利用GPU加速的图形框架,可以参考Qt Quick中对应的模块。文章来源:https://www.toymoban.com/news/detail-410913.html
上面提到的优化策略,都是有局限性的,我们在实际使用的时候,要考虑自己的业务场景和软硬件性能,不能盲目套用,要不有可能对性能产生负面影响。最好能在优化前后对对应的指标进行测试,确保优化策略确实提升了性能。文章来源地址https://www.toymoban.com/news/detail-410913.html
到了这里,关于QGraphicsView图形视图框架使用(五)渲染优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!