我的QGraphicsScene
. 我想将所有这 1000 个项目移动到新位置。新职位之间不相关,所有职位都应该同时完成。
一种方法是遍历这 1000 个项目并调用setPos
每个项目!我认为这会阻止用户界面。另一种方法是在另一个线程中绘制图像并将此图像设置为 QGraphicsScene 中的结果!
愿你有另一个想法。我期待着听到这个!
3 回答
如果你了解它的工作原理,Qt 绘图会非常快,即使你想绘制,例如,1000 条鱼都独立移动。
在大量项目的情况下,最糟糕的处理方法是为每个项目创建一个单独的 QGraphicsItem / QGraphicsObject 并尝试独立移动和绘制它们。人们在这里没有意识到的一个主要问题是,当调用paint(QPainter *painter...) 函数时,他们将笔和画笔设置在painter 上。通常,没关系,但是这样做会产生开销,因为在内部,图形管道将停止。对于 1000 个项目,这确实会减慢速度。
相反,如果我们将鱼设计为一群鱼并只创建一个 QGraphicsItem,我们可以在内部跟踪它们的位置并且只调用一次绘制函数。
class SchoolOfFish : QGraphicsObject // QGraphicsObject for signals / slots
{
Q_OBJECT
public:
void UpdateFish();
protected:
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0); // overloaded paint function
private:
QList<QPoint> m_fishPositionList;
};
请注意,鱼的所有位置都保存在 QPoint 对象的 QList 中。有几个优化可以在这里完成。首先,我经常看到人们在绘画功能中更新项目位置,这导致性能不佳;只有绘图功能应该在绘画中完成。
更新鱼的位置最初可以在计时器上完成,目标可能是每秒 30 帧。如果这太慢了,那么我们可以创建一个单独的线程来更新所有鱼的位置并将列表发送回 SchoolOfFish 对象;所有图形渲染都必须在主线程上完成。
这种方法实际上只是将鱼群视为一个粒子系统。在以这种方式设计系统之后,如果需要,我希望进行的最后一次优化将转向 OpenGl。但是,请注意,您实际上可以获得标准的 Qt 绘制调用以使用 OpenGl 作为 QWidget 状态的文档
要使用 OpenGL 进行渲染,只需调用 setViewport(new QGLWidget)。QGraphicsView 拥有视口小部件的所有权。
对于在 Qt 中绘制大量项目,您可能最好通过移动到较低级别的绘图界面来获得更好的服务。例如,OpenGL 可以在 QWindow 上实现(可以锚定到主窗口中),请参见http://qt-project.org/doc/qt-5.0/qtgui/openglwindow.html。进入 OpenGL 可能有点痛苦,但你不必担心阻塞,我当前的项目正是这样做的,它可以在大约 100 毫秒内渲染出 300,000 个彩色方块。
动态场景中的显着加速setPos()
可以通过以下方式实现:
QGraphicsScene scene;
scene.setItemIndexMethod(QGraphicsScene.NoIndex);
这比动态场景的默认设置要快得多QGraphicsScene.BspTreeIndex
,但要付出代价,因为需要查询的事件QGraphicsScene
现在会慢很多(例如悬停事件)。
另一种加快速度的方法是减少对象的总数。如果场景使用了很多QGraphicsItemGroup
,可以尝试用普通的替换它们QGraphicsItem
并覆盖它的paint()
方法而不是使用子对象。
也就是说,即使进行了这种优化,我发现一旦超过几百个对象,QGraphicsScene 的性能仍然非常糟糕。QtQuick 似乎可以更好地处理大型对象集合。