QML(聲明式 UI)與 C++(業務邏輯)交互是 Qt Quick 開發核心。本文系統梳理三種主流方式。
Qt 的元對象系統讓 C++ 對象的屬性、信號、槽、可調用方法 在運行時可被 QML 訪問。關鍵類:
QQmlEngine / QDeclarativeEngine:QML 運行環境。QQmlContext / QDeclarativeContext:上下文,暴露 C++ 對象給 QML。QQmlComponent / QDeclarativeComponent:加載 QML 文件創建對象。// C++ 類定義
class MyClass : public QObject {
Q_OBJECT
Q_PROPERTY(QString myString READ myString WRITE setMyString NOTIFY myStringChanged)
public:
Q_INVOKABLE QString getMyString() { return m_string; }
QString myString() const { return m_string; }
public slots:
void setMyString(QString s) { if (m_string!=s) { m_string=s; emit myStringChanged(); } }
signals:
void myStringChanged();
private:
QString m_string;
};
// main.cpp 暴露實例
MyClass myObj;
engine.rootContext()->setContextProperty("myCppObject", &myObj);
// 訪問屬性(無括號)
label.text = myCppObject.myString
// 調用 Q_INVOKABLE 方法(有括號)
label.text = myCppObject.getMyString()
// 連接信號
Connections { target: myCppObject; onMyStringChanged: { ... } }
// main.cpp qmlRegisterType("MyModule", 1, 0, "MyClassType");
// QML
import MyModule 1.0
MyClassType { id: myObj } // QML 中創建實例
Button { onClicked: label.text = myObj.getMyString() }
C++ 發射信號 → QML Connections 捕獲:
// QML
Connections {
target: myCppObject
onMyStringChanged: label2.text = "Signal received"
}
信號參數可直接在 QML 中使用(如 onStatusChanged(status))。命名規則:on + 信號名(首字母大寫)。
利用 QMetaObject::invokeMethod:
// QML 定義函數
function myQmlFunction(msg) { console.log(msg); return "ok"; }
// C++ 調用
QObject* qmlObj = component.create();
QVariant ret, arg = "Hello from C++";
QMetaObject::invokeMethod(qmlObj, "myQmlFunction",
Q_RETURN_ARG(QVariant, ret),
Q_ARG(QVariant, arg));
qDebug() << "Return:" << ret.toString();
參數與返回值均用 QVariant 傳遞。
Q_PROPERTY + NOTIFY)實現數據同步,避免手動信號連接。QObject,UI 類可繼承 QQuickItem。QAbstractItemModel 而非逐個屬性。