2016-02-22 24 views
7

Czy istnieje "prosty" sposób na wyświetlenie FPS (liczba klatek na sekundę) w aplikacji QML/C++. Wszystkie animacje i widoki są wykonywane w języku QML, a logika aplikacji jest w języku C++.Pokaż FPS w QML

Próbowałem już ustawienie QML_SHOW_FRAMERATE w systemie Linux przed uruchomieniem aplikacji, ale to nie pomogło:

export QML_SHOW_FRAMERATE=1 

Odpowiedz

5

Musisz utworzyć własną FPS QQuickItem (lub QQuickPaintedItem) i zarejestrować się w main.cpp być dostępne w Twoim kodzie QML.

Oto przykład.

class FPSText: public QQuickPaintedItem 
{ 
    Q_OBJECT 
    Q_PROPERTY(int fps READ fps NOTIFY fpsChanged) 
public: 
    FPSText(QQuickItem *parent = 0); 
    ~FPSText(); 
    void paint(QPainter *); 
    Q_INVOKABLE int fps()const; 

signals: 
    void fpsChanged(int); 

private: 
    void recalculateFPS(); 
    int _currentFPS; 
    int _cacheCount; 
    QVector<qint64> _times; 
}; 

FPSText::FPSText(QQuickItem *parent): QQuickPaintedItem(parent), _currentFPS(0), _cacheCount(0) 
{ 
    _times.clear(); 
    setFlag(QQuickItem::ItemHasContents); 
} 

FPSText::~FPSText() 
{ 
} 

void FPSText::recalculateFPS() 
{ 
    qint64 currentTime = QDateTime::currentDateTime().toMSecsSinceEpoch(); 
    _times.push_back(currentTime); 

    while (_times[0] < currentTime - 1000) { 
     _times.pop_front(); 
    } 

    int currentCount = _times.length(); 
    _currentFPS = (currentCount + _cacheCount)/2; 
    qDebug() << _currentFPS; 

    if (currentCount != _cacheCount) fpsChanged(_currentFPS); 

    _cacheCount = currentCount; 
} 

int FPSText::fps()const 
{ 
    return _currentFPS; 
} 

void FPSText::paint(QPainter *painter) 
{ 
    recalculateFPS(); 
    //qDebug() << __FUNCTION__; 
    QBrush brush(Qt::yellow); 

    painter->setBrush(brush); 
    painter->setPen(Qt::NoPen); 
    painter->setRenderHint(QPainter::Antialiasing); 
    painter->drawRoundedRect(0, 0, boundingRect().width(), boundingRect().height(), 0, 0); 
    update(); 
} 

QML:

FPSText{ 
     id: fps_text 
     x:0 
     y: 0; 
     width: 200 
     height: 100 
     Text { 
       anchors.centerIn: parent 
       text: fps_text.fps.toFixed(2) 
      } 
    } 

można uzyskać dowolną inną implementację w Internecie z szybkiego wyszukiwania.

+1

dziękuję bardzo! To wydaje się działać. Czy numer jest reprezentatywny dla liczby klatek na sekundę całego widoku/aplikacji, czy tylko pomalowanego prostokąta? Czy możesz podać szybkie wyjaśnienie, jak to działa? – luffy

+1

@lipy FPSText jest zarządzany przez QML Scene Graph: http://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph.html, a punktem na powyższym kodzie jest scredowanie przerysowywania każdej klatki jest FPSText :: update() http://doc.qt.io/qt-5/qquickpainteditem.html#update –

+0

Napraw mnie, jeśli się mylę, ale .. To potencjalnie spowoduje utworzenie nieskończonej pętli z konsekwencją drenażu zasobów. –

0

Licznik QML QML, bez wpływu na wydajność.

Projekt QNanoPainter i inne w qt-labs używają odświeżenia animacji elementu QML do utworzenia licznika FPS. Tak łatwo jest zrobić, dołączając projekt wykorzystujący tę technikę (zmodyfikowany z QNanoPainter FPS counter). Kod

FpsItem:

import QtQuick 2.0 
import QtQuick.Window 2.2 

Rectangle { 
    id: root 
    property int frameCounter: 0 
    property int frameCounterAvg: 0 
    property int counter: 0 
    property int fps: 0 
    property int fpsAvg: 0 

    readonly property real dp: Screen.pixelDensity * 25.4/160 

    color: "black" 
    width: childrenRect.width + 10*dp; 
    height: childrenRect.height + 10*dp; 

    Image { 
     id: spinnerImage 
     anchors.verticalCenter: parent.verticalCenter 
     x: 4 * dp 
     width: 36 * dp 
     height: width 
     source: "images/spinner.png" 
     NumberAnimation on rotation { 
      from:0 
      to: 360 
      duration: 800 
      loops: Animation.Infinite 
     } 
     onRotationChanged: frameCounter++; 
    } 

    Text { 
     anchors.left: spinnerImage.right 
     anchors.leftMargin: 8 * dp 
     anchors.verticalCenter: spinnerImage.verticalCenter 
     color: "#c0c0c0" 
     font.pixelSize: 18 * dp 
     text: "Ø " + root.fpsAvg + " | " + root.fps + " fps" 
    } 

    Timer { 
     interval: 2000 
     repeat: true 
     running: true 
     onTriggered: { 
      frameCounterAvg += frameCounter; 
      root.fps = frameCounter/2; 
      counter++; 
      frameCounter = 0; 
      if (counter >= 3) { 
       root.fpsAvg = frameCounterAvg/(2*counter) 
       frameCounterAvg = 0; 
       counter = 0; 
      } 
     } 
    } 
} 

Używanie go jako:

import QtQuick 2.9 
import QtQuick.Window 2.2 

Window { 
    visible: true 
    width: 640 
    height: 480 
    title: qsTr("Hello World") 

    FpsItem { 
     id: fpsItem 
     anchors.centerIn: parent 
    } 

}