我已经制作了一个小型代码来使用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绩效。您当前没有使用自定义项目,但是我认为阅读该文章是有益的。