QgraphicsView慢速,大量QgraphicsPixMapiTem

QGraphicsView slow with lots of QGraphicsPixmapItem

本文关键字:QgraphicsPixMapiTem 大量 慢速 QgraphicsView      更新时间:2023-10-16

我已经制作了一个小型代码来使用qtcreator测试qgraphicsview。

代码非常简单,刚刚创建了一个从Qgraphicsview继承的类,上面有Qgraphicsscene。用大量的QgraphicsPixMapiTem(在这种情况下为2000年)填充场景,并将它们随机放置在场景中。

然后在自定义类内部并使用qtimer移动场景的所有元素。

(添加了第二个QTimer,以查看第一个QTimer的每秒次数)。

它与几百个元素的效果很好,但是如果元素数量增加,则性能下降。

有人可以给我暗示如何提高性能吗?也许使用QLIST访问元素很慢...或将QTimer用于此简单动画是一个非常糟糕的主意...或者只需在某个地方添加一些优化标志...也许忘记QgraphicsView,尝试QTQUICK和QML ...

最终应用程序应在屏幕上绘制大量图像,并使用png图像作为源来对其中一些图像进行动画。

test.pro

QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = test
TEMPLATE = app

SOURCES += main.cpp 
    c_view.cpp
HEADERS  += 
    c_view.h
FORMS    +=
RESOURCES += 
    res.qrc

c_view.h

#ifndef C_VIEW_H
#define C_VIEW_H
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QTimer>
class C_View : public QGraphicsView
{
    Q_OBJECT
public:
    C_View();
    QGraphicsScene *scene;
    QGraphicsTextItem *label_fps;
    QTimer timer;
    QTimer timer_fps;
    int interval=0;
    int fps=0;
private slots:
    void random_move();
    void show_fps();
};
#endif // C_VIEW_H

c_view.cpp

#include "c_view.h"
C_View::C_View()
{
    this->scene = new QGraphicsScene();
    this->setScene(this->scene);
    // Label to see how many times per seconds the random_move function gets called
    this->label_fps=new QGraphicsTextItem();
    this->label_fps->setDefaultTextColor(Qt::black);
    this->label_fps->setFont(QFont("times",16));
    this->label_fps->setPos(10,10);
    this->scene->addItem(this->label_fps);
    // Qtimer to enter random_move function
    connect(&this->timer,SIGNAL(timeout()),this,SLOT(random_move()));
    //this->interval=10; // 100 FPS?
    this->interval=25; // 40 FPS?
    //this->interval=50; // 20 FPS?
    //this->interval=100; // 10 FPS?
    this->timer.setInterval(this->interval);
    this->timer.start();
    // QTimer to update the FPS label
    connect(&this->timer_fps,SIGNAL(timeout()),this,SLOT(show_fps()));
    this->timer_fps.setInterval(1000); // Once a second
    this->timer_fps.start();
}
// Funcion that moves a bit all the items of the scene
void C_View::random_move()
{
    QList <QGraphicsItem*> l = this->items();
    int ini=0;
    for(int i=ini;i<l.size();i++)
    {
        l[i]->setPos(l[i]->x()+(rand()%3)-1,l[i]->y()+(rand()%3)-1);
    }
    this->fps++;
}
// Just show how many times random_move function gets call, since last time
void C_View::show_fps()
{
    this->label_fps->setPlainText("FPS "+QString::number(this->fps));
    this->label_fps->setZValue(1);
    this->fps=0;
}

main.cpp

#include <QApplication>
#include "c_view.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    C_View *view = new C_View();
    // Fill the QGraphicsView with lots of images
    for(int i=0;i<2000;i++)
    {
        QGraphicsPixmapItem *item=new QGraphicsPixmapItem();
        item->setPixmap(QPixmap(":/images/p.png").scaled(100,100));
        item->setPos(rand()%view->width(),rand()%view->height());
        view->scene->addItem(item);
    }
    view->show();
    return a.exec();
}
在我看来,

放弃QT的建议有点宿命和过早。我们的应用程序使用QGraphicsScene和数万个项目,我们的性能良好。但是,他们中的大多数不是图像,但我们不会一次移动成千上万的图像。切换到其他东西可能最终是这种情况,但首先值得一些其他实验。

如果您有一个,当然可以为您提供帮助。我们使用Visual Studio,Profiler在那里运行良好,但是我不知道QT创建者是否具有任何分析能力。您的示例应用程序非常简单,我看不出任何明显的更改,但是分析通常非常揭示。

由于您在场景中移动东西,因此请尝试QGraphicsScene :: SetIteMindexMethod和Qgraphicsscene :: SetBsptreedeptepth的选项。这些设置的推荐设置因您倾向于使用场景而异。

我认为,每秒移动2000个项目似乎很多。您说您的最终应用程序有很多图像,但只有其中一些动作。您是否希望其中2000人会移动?

另外,您正在使用什么版本的QT?以后的版本对要使用的渲染引擎做出了更好的决定,我们的经验是,它非常好。

显示视图后(例如,在主函数中)启动计时器。那应该解决这种奇怪的行为。编辑:不,什么都不会改变。尝试

setViewportUpdateMode(BoundingRectViewportUpdate);
//setCacheMode(QGraphicsView::CacheBackground);

而是。这是文档:setViewPortupDateMode |setCachemode。不要忘记阅读这些函数参数类型。

另一方面,通常您不需要处理QGraphicsScene的指针,因为此类为您提供了Scene()函数。如果您的代码确实需要此指针,我认为将您的属性命名为M_Scene(或除了Scene()函数名称以外的其他任何内容)更方便。

edit2

提高渲染速度的另一种方法是降低场景项目的边界矩形。为此,您可以将PixMap项目扩展到50*50(例如)而不是100*100。实际上,场景项目碰撞的较少,QT渲染过程将会更快。此外,这是一篇文章在使用自定义的QGraphicSitem内部QgraphicsView时发出一些优化技巧:QT:改善Qgraphicsview绩效。您当前没有使用自定义项目,但是我认为阅读该文章是有益的。