想象一个巨大的矩形网格填充瓷砖.单个图块不是很复杂,它们是包含少量形状的svg图像.
不同类型的瓷砖数量不是很大,我估计在低数百.然而,网格可能变得非常大,因此总瓦片的数量是巨大的(至少数万,甚至更多).
我必须能够平滑地水平和垂直地滚动网格,以及平滑地放大和缩小网格.我也必须能够跳到特定的位置.
如果我可以异步填充它,首先是实际可见的元素,然后是其余元素,这也是很好的.这意味着我首先必须在循环中添加行和列的表处理类不是最佳解决方案,因为起始位置不一定是左上角.
通过将图块中的项目的所有width和height属性指定为缩放因子的倍数来简单地实现缩放.这svg不应该是一个问题,因为不同图像的数量不高,它应该能够被缓存.在不太可能的情况下svg成为瓶颈,我可以png在不同的分辨率中使用不同的s 组.
我尝试(或考虑)了以下方法:
使用SameGame示例的方法,动态创建QML对象(Component.createObject).如果对象的数量很少,但是对于大量对象来说非常慢,这是有效的.即使对象完全是空的,这种方法也需要很长时间.
使用Repeater内部a Flickable.该Flickable包含Grid,这是由一个人口Repater.的Grid,当然,是巨大的.此方法比动态创建对象更快,但随着切片数量的增长仍然效率低下.QML引擎跟踪每个项目,甚至是那些不可见的项目.缩放也很慢,因为每个项目的属性都会重新计算,而不仅仅是可见的属性.
用一个GridView.这看起来像乍一看的完美解决方案.在GridView继承Flickable,也需要照顾到仅渲染的是视图的范围内的内容.即使是具有数百万svg图像的测试用例运行速度也相当快,并且可以平滑地滚动和调整大小.只有一个问题:GridView只能水平或垂直滑动,但不能同时滑动.自2012年以来一直有关于此的功能请求,但它似乎仍然被忽略.
QGraphicsView直接使用.它能够显示,滚动和缩放所需的元素数量,但它不是基于QML的.我的GUI的其余部分是QML,我只阅读有关组合QML和的恐怖故事QGraphicsView.我从未见过任何合理的例子.
还有哪些其他解决方案?一些可怕的黑客使用Javascript来添加和删除简单的行和列GridLayout(只有几行和大于可见区域的列),而它在一个Flickable?或者只是嵌入一个OpenGL窗口并手动绘制所有内容?
我希望这不应该是一项不可能完成的任务.20多年前为DOS和Windows 95编写的策略游戏可以处理这些数量的磁贴,同时还具有纹理和动画.
是的,多年来,Qt 非常擅长忽略社区建议,即使它们非常有用、被认为很重要、并且恰好是得票最多的,例如zip 支持。
我个人不会费心“修复” GridView,而是用 C++ 从头开始实现一些适合我的特定要求的东西,这样它既快速又高效。如果你的图块是统一的正方形,这将非常容易,而且听起来你可以逃脱惩罚,即使里面的实际图像不是正方形。这将非常容易以编程方式确定它们的位置,并确定左上角的图块、每行的图块数量以及后续行的步幅。然后,随着可见性矩形的移动,您将迭代容器和信号,为进入可见性的元素创建 QML 元素。十分简单。
您不需要任何花哨的东西,只需继承QObject,将类型注册到 QML,然后填充它的内部“模型”。你肯定不希望所有的对象都在内存中,即使场景图足够智能,不会渲染它们,它仍然会处理它们,我怀疑你的 FPS 下降不是 GPU 的产物,而是 CPU 瓶颈。
实际的网格对象可以用它们的数据发出创建和销毁信号Q_SIGNAL void create(x, y, imgPath);,因此您可以在 QML 端绑定自定义处理程序,这将为您提供灵活性和易用性,例如轻松指定“委托”对象,它会比在 C++ 中进行实际的创建/销毁。您可以对 QML 端的少数项目使用绑定,这些项目在离开屏幕进行自毁时可以进行跟踪,这将最大限度地降低复杂性,因为您不必跟踪所有“活动”对象。
Component {
id: objComponent
Image {
property bool isVisible: { is in grid.visibleRect ??? }
onIsVisibleChanged: if (!isVisible) destroy()
}
}
MyGrid {
id: grid
contentX: flickable.contentX
contentY: flickable.contentY
onCreate: objComponent.createObject(flickable.contentItem, {"x" : x, "y" : y, "source" : imgPath})
}
Flickable {
id: flickable
contentWidth: grid.contentWidth
contentHeight: grid.contentHeight
}
Run Code Online (Sandbox Code Playgroud)
通常,当用户有一个问题,重要到足以提供赏金时,我会生成工作代码,但不幸的是我目前太忙了。这个概念非常简单,实施起来应该不会有太大问题。
| 归档时间: |
|
| 查看次数: |
748 次 |
| 最近记录: |