2016-02-22 3 views
7

Есть ли «простой» способ показать FPS (частоту кадров) в приложении QML/C++. Все анимации и представления выполняются в QML, а логика приложения - на C++.Показать FPS в QML

Я уже попытался установить QML_SHOW_FRAMERATE в Linux перед запуском приложения, но это не помогло:

export QML_SHOW_FRAMERATE=1 

ответ

5

Вы должны создать свой собственный FPS QQuickItem (или QQuickPaintedItem) и зарегистрировать в вашем main.cpp быть доступный в вашем QML-коде.

Вот пример.

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) 
      } 
    } 

Вы можете получить любую другую реализацию в Интернете с быстрым поиском.

+1

большое спасибо! Кажется, это работает. Является ли число, показанное показателем fps всего вида/приложения, или только окрашенного прямоугольника? Не могли бы вы дать краткое объяснение того, как это работает? – luffy

+1

@luffy FPSText управляется графиком сцены QML: http://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph.html, а точка над кодом для раскладки каждого кадра - FPSText :: update() http://doc.qt.io/qt-5/qquickpainteditem.html#update –

+0

Исправьте меня, если я ошибаюсь, но .. Это потенциально создаст бесконечный цикл с учетом утечки ресурсов. –

0

QML Счетчик FPS, не влияя на производительность.

Проект QNanoPainter и другие в qt-labs используют обновление анимации QML-элемента для создания счетчика FPS. Это так легко сделать, приложил проект, который использует этот метод (изменен от QNanoPainter FPS counter).

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; 
      } 
     } 
    } 
} 

Используя его как:

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 
    } 

} 
Смежные вопросы