2013-08-23 28 views
3

我的QGraphicsScene中有大约1000个图形项目。我想将所有这1000个项目移动到新位置。新的职位不相互关联,所有职位都应该在同一时间完成。
一种方法是遍历这1000个项目,并为每个项目调用setPos!我认为这会阻止用户界面。另一种方法是在另一个线程中绘制图像,并将该图像设置为QGraphicsScene的结果!
愿您有另一个想法,我期待着听到!如何在不阻挡UI的情况下在QGraphicsScene中移动1000个项目

+0

1000个项目通常意味着您的UI设计出了问题,或者您应该进行优化(如果没有更多细节,很难说出有用的东西)。 –

+2

@MarekR:什么?这与UI设计无关!问题很简单:假设你的QGraphicsScene中有1000条鱼,并且你想同时随机移动它们! – saeed

+0

可以在单个容器中更有效地绘制群体物品。一切都取决于细节。无论如何,如果一切正常完成,标准台式机上的1000个简单物品应该不成问题。 –

回答

7

如果你了解它是如何工作的,即使你想绘制,例如,1000条鱼都独立移动,Qt绘图可以非常快。

在大量项目的情况下,处理这种情况最糟糕的方式是为每个项目创建一个单独的QGraphicsItem/QGraphicsObject,并尝试独立移动和绘制它们。人们在这里没有意识到的一个主要问题是,当绘画(QPainter *画家...)功能被调用时,他们将笔和笔刷放在画家身上。通常情况下,没关系,但是在内部有这样做的开销,图形管道将会停滞。对于1000件商品,这确实会减慢速度。相反,如果我们将鱼设计为鱼群并创建一个QGraphicsItem,我们可以在内部跟踪它们的位置,并且只需调用一次paint函数。

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对象;所有图形渲染必须在主线程上完成。

这种方法实际上只是把鱼群当做particle system。以这种方式设计系统后,如果需要的话,我希望做的最后一个优化将转向OpenGl。但是请注意,其实你可以得到标准的Qt油漆调用来使用OpenGL作为QWidget的状态的文档

要渲染使用OpenGL,只需调用setViewport(新QGLWidget来绘图)。 QGraphicsView取得了视口控件的所有权。

QGraphicsScene scene; 
scene.setItemIndexMethod(QGraphicsScene.NoIndex); 

这是不是默认QGraphicsScene.BspTreeIndex对动态场景快得多,但也是有代价的,因为这需要事件:

+0

谢谢!完美答案。正是我在看的东西! – saeed

+0

Qt QML支持粒子系统:http://qt-project.org/doc/qt-5.0/qtquick/qtquick-particles2-qtquick-effects-particles.html –

2

对于在Qt中绘制大量项目,通过移动到较低级别的绘制界面可能会更好。例如,OpenGL可以在QWindow上实现(可以将它锚定到主窗口中),请参阅http://qt-project.org/doc/qt-5.0/qtgui/openglwindow.html。 OpenGL可能有点痛苦,但您不必担心阻塞,我目前的项目完全是这样做的,以便在大约100毫秒内呈现300,000个彩色方块。

+0

谢谢。你在哪里学习OpenGL :) – saeed

+0

我链接的例子将让你了解Qt中OpenGL的基础知识。除此之外,你可以阅读普通的OpenGL教程(忽略GLUT这个只是另一个窗口系统的讨论) - 比如http://www.opengl-tutorial.org/或http://lazyfoo.net/tutorials/OpenGL/。 –

0

动态场景的setPos()大幅加快可实现查询QGraphicsScene现在将显着较慢(例如悬停事件)。

另一种加快速度的方法是减少对象的总数。如果场景使用很多QGraphicsItemGroup,则可以尝试用普通的QGraphicsItem替换它们,并覆盖它的paint()方法而不是使用子对象。即使有了这种优化,我发现一旦超过了几百个对象,QGraphicsScene的性能仍然相当悲惨。 QtQuick似乎更好地处理大型对象集合。

相关问题