- 1. 背景需求
- 2. 实现步骤
- 2.1. 定义 Model(数据模型)
- 2.1.1. DataModel.h
- 2.1.2. DataModel.cpp
- 2.2. 定义 ViewModel(视图模型)
- 2.2.1. PersonViewModel.h
- 2.2.2. PersonViewModel.cpp
- 2.3. 在 QML 中使用 ViewModel
- 2.3.1. main.cpp
- 2.4. QML 文件
- 2.4.1. main.qml
- 2.5. 运行效果
- 2.5.1. 总结
- 2.1. 定义 Model(数据模型)
1. 背景需求
在 QML 中加载 C++ 数据是一种常见的需求,尤其是在需要处理复杂逻辑或调用系统功能时。通过将 C++ 数据和功能暴露给 QML,可以充分利用 Qt 的强大功能。
在C#开发有代码后置的概念,比如MVVM模式,这种做法有助于将界面展示逻辑与业务逻辑分离,提高代码的可维护性和可测试性。
QML中通常通过在QML文件中引用外部JavaScript文件或C++类来实现。可以将逻辑代码放在单独的 JavaScript 文件中,或者使用 C++ 来实现更复杂的逻辑。这样也能让 QML 代码保持简洁。称之为代码后置。
关于MVVM设计模式的实现,QML非常适合实现,因为它支持数据绑定,可以轻松地将视图与视图模型连接起来。以下是一个简单的示例,展示如何在QML中应用MVVM模式:
好的,以下是一个使用 C++ 来定义 Model 和 ViewModel,并在 QML 中使用的完整示例。
2. 实现步骤
2.1. 定义 Model(数据模型)
Model 是数据的来源,通常是一个简单的类,用于存储和管理数据。
2.1.1. DataModel.h
#ifndef DATAMODEL_H
#define DATAMODEL_H
#include <QObject>
#include <QString>
class DataModel : public QObject {
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged)
public:
explicit DataModel(QObject *parent = nullptr);
QString name() const;
void setName(const QString &name);
int age() const;
void setAge(int age);
signals:
void nameChanged();
void ageChanged();
private:
QString m_name;
int m_age;
};
#endif // DATAMODEL_H
2.1.2. DataModel.cpp
#include "DataModel.h"
DataModel::DataModel(QObject *parent) : QObject(parent) {
m_name="";
m_age=0;
}
QString DataModel::name() const {
return m_name;
}
void DataModel::setName(const QString &name) {
if (m_name != name) {
m_name = name;
emit nameChanged();
}
}
int DataModel::age() const {
return m_age;
}
void DataModel::setAge(int age) {
if (m_age != age) {
m_age = age;
emit ageChanged();
}
}
2.2. 定义 ViewModel(视图模型)
ViewModel 是 Model 和 View 之间的桥梁,负责处理业务逻辑和数据绑定。
2.2.1. PersonViewModel.h
#ifndef PERSONVIEWMODEL_H
#define PERSONVIEWMODEL_H
#include <QObject>
#include "DataModel.h"
class PersonViewModel : public QObject {
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged)
public:
explicit PersonViewModel(QObject *parent = nullptr);
QString name() const;
void setName(const QString &name);
int age() const;
void setAge(int age);
signals:
void nameChanged();
void ageChanged();
private:
DataModel *m_model;
};
#endif // PERSONVIEWMODEL_H
2.2.2. PersonViewModel.cpp
#include "PersonViewModel.h"
PersonViewModel::PersonViewModel(QObject *parent) : QObject(parent), m_model(new DataModel(this)) {}
QString PersonViewModel::name() const {
return m_model->name();
}
void PersonViewModel::setName(const QString &name) {
m_model->setName(name);
emit nameChanged();
}
int PersonViewModel::age() const {
return m_model->age();
}
void PersonViewModel::setAge(int age) {
m_model->setAge(age);
emit ageChanged();
}
2.3. 在 QML 中使用 ViewModel
在 main.cpp
中,将 PersonViewModel
注册到 QML 引擎中,使其可以在 QML 文件中使用。
2.3.1. main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "PersonViewModel.h"
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
// 创建 PersonViewModel 实例并注册到 QML
PersonViewModel viewModel;
engine.rootContext()->setContextProperty("viewModel", &viewModel);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
2.4. QML 文件
在 QML 文件中,通过 viewModel
对象访问和更新数据。
2.4.1. main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 400
height: 300
title: "MVVM Example"
Column {
anchors.centerIn: parent
spacing: 10
Text {
text: "Name: " + viewModel.name
}
TextField {
placeholderText: "Enter name"
text: viewModel.name
onEditingFinished: viewModel.name = text
}
Text {
text: "Age: " + viewModel.age
}
TextField {
placeholderText: "Enter age"
text: viewModel.age.toString()
onEditingFinished: viewModel.age = parseInt(text)
}
}
}
2.5. 运行效果
- ViewModel:
PersonViewModel
提供了name
和age
属性,并通过Q_PROPERTY
定义了这些属性的 getter 和 setter 方法。 - Model:
DataModel
存储了实际的数据,并通过信号通知 ViewModel 数据的变化。 - View:QML 文件通过
viewModel
对象访问和更新数据,实现了双向数据绑定。
当你运行程序时,你可以通过输入框修改 name
和 age
的值,这些值会实时更新到 Model 中,并反映在界面上。
2.5.1. 总结
通过这种方式,你可以在 QML 中实现类似于 C# 的 MVVM 模式,将数据(Model)、业务逻辑(ViewModel)和用户界面(View)分离,提高代码的可维护性和可测试性。