2

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

代码很简单,只是创建了一个继承自 QGraphicsView 的类,上面有一个 QGraphicsScene。用大量缩放到 100x100 的 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;
}

主文件

#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();
}
4

2 回答 2

3

在我看来,放弃 Qt 的建议有点宿命论和为时过早。我们的应用程序使用具有数万个项目的 QGraphicsScene,我们有很好的性能。然而,它们中的大多数都不是图像,而且我们一次也不会移动数千个。切换到其他东西可能最终会出现这种情况,但首先值得进行一些额外的实验。

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

由于您要在场景中移动物体,请尝试使用 QGraphicsScene::setItemIndexMethod 和 QGraphicsScene::setBspTreeDepth 的选项。推荐的设置取决于您倾向于使用场景的方式。

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

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

于 2016-12-12T20:04:21.203 回答
0

在您的视图出现后启动您的计时器(例如在 main 函数中)。那应该可以解决这种奇怪的行为。编辑:不,这不会改变任何事情。尝试

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

反而。以下是文档:setViewportUpdateMode | 设置缓存模式。不要忘记阅读这些函数参数类型。

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

编辑2

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

于 2016-12-11T21:51:54.433 回答