我使用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();
}
答案 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。您目前还没有使用自定义项目,但我认为阅读该文章会有所帮助。