// fpscounter.h
#ifndef FPSCOUNTER_H
#define FPSCOUNTER_H
#include <QObject>
#include <QQuickItem>
#include <QElapsedTimer>
class FpsCounter : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(qreal fps READ fps NOTIFY fpsChanged)
public:
explicit FpsCounter(QQuickItem *parent = nullptr);
qreal fps() const { return m_fps; }
protected:
void timerEvent(QTimerEvent *event) override;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
signals:
void fpsChanged();
private:
qreal m_fps;
int m_frameCount;
QElapsedTimer m_timer;
};
#endif // FPSCOUNTER_H
// fpscounter.cpp
#include "fpscounter.h"
#include <QTimerEvent>
FpsCounter::FpsCounter(QQuickItem *parent)
: QQuickItem(parent)
, m_fps(0)
, m_frameCount(0)
{
setFlag(ItemHasContents);
m_timer.start();
startTimer(1000); // 每秒更新一次
}
void FpsCounter::timerEvent(QTimerEvent *event)
{
Q_UNUSED(event)
qreal elapsed = m_timer.elapsed() / 1000.0;
m_fps = m_frameCount / elapsed;
m_frameCount = 0;
m_timer.restart();
emit fpsChanged();
}
QSGNode *FpsCounter::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
m_frameCount++;
return oldNode;
}
注册 C++ 类到 QML:
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "fpscounter.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<FpsCounter>("Custom", 1, 0, "FpsCounter");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
在 QML 中使用 C++ 实现:
// main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import Custom 1.0 // 导入自定义模块
Window {
visible: true
width: 640
height: 480
title: qsTr("FPS Counter")
FpsCounter {
id: fpsCounter
anchors.top: parent.top
anchors.left: parent.left
width: 100
height: 30
Text {
anchors.fill: parent
text: "FPS: " + Math.round(parent.fps)
color: "white"
}
}
}
另一种 C++ 实现方式(使用 QQuickWindow):
// fpscounter.h
class FpsCounter : public QObject
{
Q_OBJECT
Q_PROPERTY(qreal fps READ fps NOTIFY fpsChanged)
public:
explicit FpsCounter(QQuickWindow *window);
qreal fps() const { return m_fps; }
private slots:
void afterRendering();
signals:
void fpsChanged();
private:
QQuickWindow *m_window;
qreal m_fps;
int m_frameCount;
QElapsedTimer m_timer;
};
// fpscounter.cpp
FpsCounter::FpsCounter(QQuickWindow *window)
: QObject(window)
, m_window(window)
, m_fps(0)
, m_frameCount(0)
{
connect(window, &QQuickWindow::afterRendering, this, &FpsCounter::afterRendering);
m_timer.start();
}
void FpsCounter::afterRendering()
{
m_frameCount++;
if (m_timer.elapsed() >= 1000) {
m_fps = m_frameCount * 1000.0 / m_timer.elapsed();
m_frameCount = 0;
m_timer.restart();
emit fpsChanged();
}
}
纯qml 方法:
// FpsCounter.qml
import QtQuick 2.15
Item {
id: root
property real fps: 0
property int frameCount: 0
property real lastTime: Date.now()
Timer {
interval: 1000 // 每秒更新一次
repeat: true
running: true
onTriggered: {
var currentTime = Date.now()
var delta = (currentTime - lastTime) / 1000
fps = frameCount / delta
frameCount = 0
lastTime = currentTime
}
}
NumberAnimation {
running: true
loops: Animation.Infinite
onRunningChanged: frameCount++
}
Text {
text: "FPS: " + Math.round(fps)
color: "white"
}
}