2

QtCreator を使用して QGraphicsView 機能をテストする小さなコードを作成しました。

コードは非常に単純で、QGraphicsScene を持つ QGraphicsView から継承されたクラスを作成しただけです。100x100 にスケーリングされた多数の QGraphicsPixmapItem (この場合は 2000) でシーンを埋め、ランダムにシーンに配置します。

次に、カスタム クラス内で QTimer を使用して、シーンのすべての要素を少し移動します。

(最初の QTimer が 1 秒間に何回呼び出されるかを確認するために、2 番目の QTimer を追加しました)。

数百の要素でうまく機能しますが、要素数が増えるとパフォーマンスが低下します。

誰かがパフォーマンスを上げる方法についてヒントをくれませんか? たぶん、QList を使用した要素へのアクセスが遅い... または、この単純なアニメーションに QTimer を使用するのは非常に悪い考えです... または、いくつかの最適化フラグをどこかに追加する必要があります... QGraphicsView を忘れて試してみてくださいQtQuickとQML ...

最終的なアプリケーションでは、画面に多数の画像を描画し、ソースとして png 画像を使用してそれらの一部をアニメーション化する必要があります。

テストプロ

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

2 に答える 2

0

ビューが表示されたらタイマーを開始します (たとえば、メイン関数で)。それはその奇妙な振る舞いを修正するはずです。編集:いいえ、何も変わりません。試す

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

代わりは。ドキュメントは次のとおりですsetCacheMode。これらの関数の引数の型について読むことを忘れないでください。

一方、通常は QGraphicsView 内で QGraphicsScene へのポインタを処理する必要はありません。このクラスは scene() 関数を提供するからです。コードでこのポインターが必要な場合は、属性 m_scene (または scene() 関数名以外の名前) に名前を付ける方が便利だと思います。

編集2

レンダリング速度を改善するもう 1 つの方法は、シーン アイテムの境界矩形を低くすることです。これを行うには、ピックスマップ アイテムを 100*100 ではなく 50*50 (たとえば) にスケーリングします。実際、衝突するシーン アイテムが少ないほど、Qt のレンダリング プロセスは速くなります。さらに、 QGraphicsView 内でカスタマイズされた QGraphicsItem を使用する場合の最適化のトリックをいくつか発行している記事があります: Qt: Improving QGraphicsView Performance。あなたは現在カスタマイズされたアイテムを使用していませんが、その記事を読むことは有益だと思います.

于 2016-12-11T21:51:54.433 に答える