QGraphicsView很慢,有很多QGraphicsPixmapItem

时间:2016-12-11 20:55:38

标签: c++ qt qgraphicsview qgraphicsscene qgraphicspixmapitem

我使用QtCreator制作了一个小代码来测试QGraphicsView功能。

代码非常简单,只是创建了一个继承自QGraphicsView的类,它上面有一个QGraphicsScene。使用大量的QGraphicsPixmapItem(在本例中为2000)填充场景,缩放到100x100并随机将它们放入场景中。

然后在自定义类中使用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();
}

2 个答案:

答案 0 :(得分:3)

在我看来,放弃Qt的建议有点宿命和不成熟。我们的应用程序使用QGraphicsScene和成千上万的项目,我们有良好的性能。但是,大多数都不是图像,我们一次也不会移动数千个图像。切换到其他东西可能最终会成为现实,但首先值得进行一些额外的实验。

如果你有一个探查器,肯定可以帮助你。我们使用Visual Studio并且分析器在那里运行良好,但我不知道Qt Creator是否具有任何分析能力。您的示例应用程序非常简单,我没有看到任何明显的变化,但分析通常非常有启发性。

由于你在场景中移动东西,试验QGraphicsScene :: setItemIndexMethod和QGraphicsScene :: setBspTreeDepth的选项。这些建议的设置取决于您使用场景的方式。

在我看来,每秒移动2000件物品似乎很多。你说你的最终应用程序有很多图像,但只有一些移动。你预计其中有2000个会移动吗?

另外,你使用的是什么版本的Qt?更高版本可以更好地决定使用渲染引擎,我们的经验是它非常好。

答案 1 :(得分:0)

在视图显示后启动计时器(例如在主函数中)。这应该解决这种奇怪的行为。 修改:不,这不会改变任何事情。尝试

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

代替。以下是文档:setViewportUpdateMode | setCacheMode。别忘了阅读那些函数参数类型。

另一方面,您通常不需要在QGraphicsView中处理指向QGraphicsScene的指针,因为此类为您提供了scene()函数。如果你的代码确实需要这个指针,我认为命名你的属性m_scene(或除了scene()函数名之外的任何东西)会更方便。

<强> EDIT2

提高渲染速度的另一种方法是降低场景项目&#39;边界矩形。为此,您可以将像素图项目缩放为50 * 50(例如)而不是100 * 100。实际上,场景项目碰撞越少,Qt渲染过程就越快。此外,这篇文章在QGraphicsView中使用自定义QGraphicsItem时发布了一些优化技巧:Qt: Improving QGraphicsView Performance。您目前还没有使用自定义项目,但我认为阅读该文章会有所帮助。