【发布时间】:2016-08-31 08:54:55
【问题描述】:
想象一个巨大的矩形网格,里面装满了瓷砖。单个图块不是很复杂,它们是包含少量形状的 svg 图像。
不同类型的瓷砖数量不是很多,我估计在几百个。但是,网格可能会变得非常大,因此总图块的数量非常庞大(至少数万,也许更多)。
我必须能够平滑地水平和垂直滚动网格,以及平滑地放大和缩小。我还必须能够跳到特定的位置。
如果我可以异步填充它也会很好,首先是实际可见的元素,然后是其余的。这意味着我首先必须在循环中添加行和列的表格处理类不是最佳解决方案,因为起始位置不一定是左上角。
缩放可以简单地通过将图块中项目的所有width 和height 属性指定为缩放因子的倍数来实现。 svg 应该不是问题,因为不同图像的数量并不多,它应该可以被缓存。在不太可能的情况下svg 成为瓶颈,我可以使用不同分辨率的不同pngs 集。
我尝试(或考虑)了以下方法:
使用SameGame example的方法,动态创建QML对象(
Component.createObject)。如果对象的数量很少,这很有效,但是对于大量的对象来说非常慢。即使对象完全为空,此方法也会采用very long time。在
Flickable中使用Repeater。Flickable包含一个Grid,它由Repater填充。当然,Grid是巨大的。 这种方法比动态创建对象要快,但随着瓦片数量的增加,效率仍然很低。 QML 引擎会跟踪每个项目,即使是那些不可见的项目。缩放也很慢,因为每个项目的属性都会重新计算,而不仅仅是可见的。使用
GridView。乍一看,这似乎是完美的解决方案。GridView继承Flickable,并且它还注意只渲染视图范围内的内容。即使是包含数百万个 svg 图像的测试用例也运行得相当快,并且它可以平滑地滚动和调整大小。只有一个问题:GridView只能水平或垂直滑动,但不能同时滑动。自 2012 年以来,关于此问题的 feature request 一直存在,但似乎仍被忽略。直接使用
QGraphicsView。它is capable 用于显示、滚动和缩放所需数量的元素,但它不是基于 QML 的。我的 GUI 的其余部分在 QML 中,我只读过关于结合QML和QGraphicsView的恐怖故事。我从未见过任何合理的例子。
还有哪些其他解决方案?在 Flickable 中移动时,使用 Javascript 添加和删除简单 GridLayout 的行和列(仅比可见区域大几行和列)的一些可怕的技巧?还是只是嵌入一个 OpenGL 窗口并手动绘制所有内容?
我希望这不应该是一项不可能完成的任务。 20 多年前为 DOS 和 Windows 95 编写的策略游戏可以处理这么多的图块,同时还具有纹理和动画。
【问题讨论】:
-
与 DOS 和 Windows 95 的比较没有任何意义,因为底层技术和方法截然不同。为什么不使用自定义 QtQuick 元素来满足您的需求?
-
@peppe :我的观点不是系统本身,而是可以用 200 倍的计算能力来做到这一点。 “自定义 QtQuick 元素”是指我应该从头开始实现我自己的 2d 图形引擎?是的,这是可能的,但这种方法类似于 OpenGL 绘图解决方案。
GridView的优势在于知道加载和卸载的内容和时间。通过从头开始做所有事情,我必须实现自己的内存管理、可见性计算等等。如果我必须从头开始实现所有内容,为什么还要使用 Qt? -
即使在今天你也完全可以,但是具有 10000 个元素的中继器是错误的方法。 QML 缺乏这样一个内置的东西并不意味着它不可能实现。
-
当您知道要显示的区域的大小和图块的大小时,可见性计算应该不难实现。然后使用带有 Loader 的中继器作为委托,并为匹配可见性约束的“活动”属性设置绑定(取决于索引)。
-
查看github.com/bjorn/tiled 来源也许你会在那里找到有用的东西