Qt Quick+C++中如何放置可重复调用的update与fixedUpdate函数?
在Qt Quick QML中实现循环调用update()和fixedUpdate()的方案
Qt Quick基于Qt事件循环运行,不需要手动编写while循环,你可以通过以下方式实现两类函数的重复调用:
1. 每帧触发的update()(通用更新)
利用Window的frameSwapped信号,该信号会在每一帧渲染完成后触发,刚好对应你原C++代码中每次循环调用的update()。
2. 固定时间间隔的fixedUpdate()(物理处理)
使用QML的Timer组件,设置固定的时间间隔并开启重复触发,用来模拟固定步长的物理更新逻辑。
方案一:C++后端 + QML调用(适合复杂逻辑)
如果你的update()和fixedUpdate()是C++实现的函数,需要先将它们暴露给QML:
C++ Engine类实现
#include <QObject> #include <QElapsedTimer> class Engine : public QObject { Q_OBJECT Q_PROPERTY(float deltaTime READ deltaTime NOTIFY deltaTimeChanged) public: explicit Engine(QObject *parent = nullptr) : QObject(parent) { timer.start(); } // 标记为可被QML调用 Q_INVOKABLE void update() { // 计算帧间隔时间(秒) m_deltaTime = timer.elapsed() / 1000.0f; timer.restart(); // 你的通用更新逻辑写在这里 emit deltaTimeChanged(); } Q_INVOKABLE void fixedUpdate() { // 你的物理处理逻辑写在这里 } float deltaTime() const { return m_deltaTime; } signals: void deltaTimeChanged(); private: QElapsedTimer timer; float m_deltaTime = 0.0f; };
注册C++类到QML(main.cpp)
#include <QGuiApplication> #include <QQmlApplicationEngine> #include "engine.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); // 注册Engine类到QML的MyEngine模块 qmlRegisterType<Engine>("MyEngine", 1, 0, "Engine"); QQmlApplicationEngine engine; const QUrl url(u"qrc:/main.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
QML调用逻辑(main.qml)
import QtQuick 2.15 import QtQuick.Window 2.15 import MyEngine 1.0 Window { width: 640 height: 480 visible: true title: qsTr("Loop Example") // 实例化C++的Engine对象 Engine { id: gameEngine } // 监听帧交换信号,每帧调用update() Connections { target: window function onFrameSwapped() { gameEngine.update(); } } // 固定间隔调用fixedUpdate(),这里设为16ms(约60次/秒) Timer { interval: 16 running: true repeat: true onTriggered: { gameEngine.fixedUpdate(); } } // 可选:显示帧间隔时间 Text { text: "Delta Time: " + gameEngine.deltaTime.toFixed(3) anchors.top: parent.top anchors.left: parent.left anchors.margins: 10 font.pixelSize: 16 } }
方案二:纯QML实现(适合简单逻辑)
如果逻辑不需要C++处理,直接在QML中定义函数并调用:
import QtQuick 2.15 import QtQuick.Window 2.15 Window { width: 640 height: 480 visible: true title: qsTr("Pure QML Loop") // 定义通用更新函数 function update() { // 你的每帧更新逻辑 console.log("Frame updated"); } // 定义物理更新函数 function fixedUpdate() { // 你的固定间隔处理逻辑 console.log("Fixed update triggered"); } // 每帧触发update() Connections { target: window function onFrameSwapped() { update(); } } // 固定间隔触发fixedUpdate() Timer { interval: 16 running: true repeat: true onTriggered: fixedUpdate() } }
关键说明
frameSwapped信号的触发时机和渲染帧率一致,适合处理和画面同步的逻辑(比如角色动画、相机跟随)。Timer的interval可以根据需求调整,比如物理模拟常用16ms(60次/秒)或33ms(30次/秒),保证处理步长稳定。- 如果你需要更精确的时间控制,也可以在C++中使用
QTimer来触发fixedUpdate(),效果和QML的Timer一致。
内容的提问来源于stack exchange,提问作者skrovno_CZ
相关产品推荐
相关产品推荐

