Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
563 views
in Technique[技术] by (71.8m points)

c++ - How to move around 1000 items in a QGraphicsScene without blocking the UI

I have around 1000 graphics item in my QGraphicsScene. I want to move all of these 1000 items to new position. New positions don't relate to each other and all of them should be done at the same time.
One way is to iterate through these 1000 items and call setPos for each one ! I think this will block user interface. Another way is to draw an image in another thread and to set this image as a result in QGraphicsScene!
May you have another idea.I'm looking forward to hearing that !

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Qt drawing can be very quick if you understand how it works, even if you want to draw, for example, 1000 fish all moving independently.

In the case of a large number of items, the worst way to handle this is to create a separate QGraphicsItem / QGraphicsObject for each item and try to move and draw them all independently. One major issue people don't realise here is that when the paint(QPainter * painter...) function is called, they set the pen and brush on the painter. Normally, that's ok, but there is an overhead doing this as internally, the graphics pipeline will be stalled. For 1000 items, that's really going to slow things down.

Instead, if we design the fish as a school of fish and create just one QGraphicsItem, we can keep track of their positions internally and have the paint function called just once.

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;
};

Note that all the positions of the fish are kept in a QList of QPoint objects. There are several optimisations that can be done here. Firstly, I often see people updating item positions in the paint function, which causes poor performance; Only drawing functionality should be done in paint.

Updating the fish positions can initially be done on a timer, perhaps aiming for 30 frames per second. If this is too slow, then we could create a separate thread that updates all the fish positions and emits the list back to the SchoolOfFish object; all graphics rendering must be done on the main thread.

This method is actually just treating the school of fish as a particle system. After designing the system this way, if required, the last optimisation I'd look to make would be moving to OpenGl. However, note that you can actually get the standard Qt paint calls to use OpenGl as the docs of QWidget state

To render using OpenGL, simply call setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport widget.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...