Qt QML and Qt Quick 简述及例程
Qt QML and Qt Quick 简述及例程
- 引言
- 一、简述
- 1.1 QML简述
- 1.2 Qt Quick简述
- 二、例程
- 2.1 新建Qt Quick应用
- 2.2 qml与c++ 实现信号和槽的数据传输
- 2.3 测试cpp中信号参数不为QVariant的情况,传输是否正常
- 三、参考链接
引言
QML
是一种声明式语言,专门用于设计用户界面,而Qt Quick
是基于QML的框架,用于构建现代、动态的UI。QML采用简洁的声明式语法,允许开发者通过类似JSON的结构快速定义UI组件和交互逻辑。与传统的命令式编程(如C++)相比,代码量更少,可读性更强,适合快速迭代和原型设计。Qt Quick支持Windows、macOS、Linux、Android和iOS等平台,通过一次编写即可部署到多个系统,减少平台适配成本。其渲染引擎(如Scene Graph)优化了性能,确保在不同设备上流畅运行。
一、简述
1.1 QML简述
QML
(Qt Meta-Object Language)是一种声明式脚本语言,用于描述应用程序的用户界面。它基于 JavaScript 语法,允许开发者通过简洁的代码定义界面元素及其交互逻辑。QML 的核心优势在于其可读性和高效性,适合快速构建动态、响应式的 UI。
1. 核心特性
:
声明式语法:通过类似 JSON 的语法定义界面元素,代码简洁易读。
数据绑定:支持属性绑定机制,自动同步数据与 UI 的变化。
JavaScript 集成:可直接嵌入 JavaScript 处理逻辑,增强交互能力。
跨平台支持:基于 Qt 框架,可部署到桌面、移动和嵌入式系统。
组件化设计:支持自定义可复用组件,提升开发效率。
2. qml与c++交互
绑定属性:通过 Q_PROPERTY 定义可绑定属性,QML 可自动同步数据变化。
信号与槽:QML 可直接调用 C++ 的信号和槽函数。
注册QML:通过 qmlRegisterType 将 C++ 类注册为 QML 类型,允许在 QML 中实例化。
上下文属性:通过 QQmlContext 将 C++ 对象或数据暴露给 QML。在 C++ 中注册对象后,QML 可直接访问其属性和方法。
1.2 Qt Quick简述
Qt Quick
是 QML 的配套框架,提供了一系列预定义的 QML 类型(如矩形、文本、动画等)和模块(如 QtQuick.Controls 用于控件)。它利用硬件加速的图形渲染引擎(Scene Graph),能够高效处理复杂动画和视觉效果。
1. 核心特性
跨平台:支持 Windows、macOS、Linux、Android 和 iOS。
硬件加速:基于不同的操作系统,灵活利用 OpenGL 或 Vulkan 实现高性能渲染。
数据绑定:通过属性绑定自动更新 UI。
C++ 集成:可将 QML 与 C++ 逻辑结合,提升性能。
2. 主要库
QtQuick 模块:提供基础的 QML 类型 (如 Item、Rectangle),包含场景图渲染引擎,优化性能
QtQuick.Controls:提供标准化 UI 控件 (如按钮、滑块、对话框),支持多种样式 (如 Material、Fusion)
QtQuick.Layouts:动态布局管理(如 RowLayout、GridLayout)
QtQuick.Dialogs:预置对话框(文件选择、颜色选择等)
QtQuick.Shapes:高级矢量图形绘制(路径、贝塞尔曲线)
QtQuick.Particles:粒子系统(用于特效如火焰、烟雾)
二、例程
2.1 新建Qt Quick应用
- 需注意:新建Qt Quick应用时,
minimum required QT version
默认选的版本可能
并没有安装, (无脑下一步可能会显示:No suitable kits found.
),需选择已安装的编译器版本。 -
- 和创建Qt窗体或控制台程序一样,可无脑下一步,结果如下所示:
- 和创建Qt窗体或控制台程序一样,可无脑下一步,结果如下所示:
-
main.cpp
中加载了qml文件,具体的显示部分在main.qml
中实现,也可在cpp文件中获取其界面上的对象进行修改,如代码所示:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>int main(int argc, char *argv[])
{QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QGuiApplication app(argc, argv);QQmlApplicationEngine engine;engine.load(QUrl(QStringLiteral("qrc:/main.qml")));if (engine.rootObjects().isEmpty())return -1;QObject *rootObject = engine.rootObjects().first();QQuickWindow *window = qobject_cast<QQuickWindow *>(rootObject);if (window) {window->setWidth(480);}return app.exec();
}
2.2 qml与c++ 实现信号和槽的数据传输
- 结果如下:
main.qml
源码:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import com.example 1.0Window {visible: truewidth: 640height: 480title: qsTr("Hello World")Backend {id: backendonSendInt: console.log("Received int from C++:", value)}Button {text: "Send Int to C++"onClicked: backend.receiveInt(1) // 发送int到C++}Button {y: 50text: "Trigger C++ Signal"onClicked: backend.sendInt(2) // 触发C++信号}
}
main.cpp
源码:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QQmlContext>class Backend : public QObject {Q_OBJECT
public:explicit Backend(QObject *parent = nullptr) : QObject(parent) {}
public slots:void receiveInt(int value) {qDebug() << "Received int from QML:" << value;}
signals:void sendInt(int value);
};int main(int argc, char *argv[])
{QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QGuiApplication app(argc, argv);qmlRegisterType<Backend>("com.example", 1, 0, "Backend");QQmlApplicationEngine engine;Backend backend;engine.rootContext()->setContextProperty("backend", &backend);engine.load(QUrl(QStringLiteral("qrc:/main.qml")));if (engine.rootObjects().isEmpty())return -1;return app.exec();
}#include "main.moc"
2.3 测试cpp中信号参数不为QVariant的情况,传输是否正常
minimum required QT version
选的是5.9,上述代码中参数是int
,传输正常。在qml改用function,而不是用onSendInt
(注:改用function,在cpp中connect信号与function后与onSendInt
可能有冲突,需删掉qml中的onSendInt
,源码在后面)。- 使用
QVariant
和 使用QString
结果如下,使用QString连接信号槽会报错,qml里function的参数应该默认就是QVariant
函数语句是js语句,是不能指定类型,只能使用
QVariant
:
main.cpp
中源码如下:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QQmlContext>class Backend : public QObject {Q_OBJECT
public:explicit Backend(QObject *parent = nullptr) : QObject(parent) {}
public slots:void receiveInt(QString value) {qDebug() << "Received int from QML:" << value;emit sendInt(value);}
signals:void sendInt(QString value);
};int main(int argc, char *argv[])
{QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QGuiApplication app(argc, argv);qmlRegisterType<Backend>("com.example", 1, 0, "Backend");QQmlApplicationEngine engine;Backend backend;engine.rootContext()->setContextProperty("backend", &backend);engine.load(QUrl(QStringLiteral("qrc:/main.qml")));if (engine.rootObjects().isEmpty())return -1;QObject *rootObject = engine.rootObjects().first();QObject::connect(&backend, SIGNAL(sendInt(QString)), rootObject, SLOT(onTest(QString)));return app.exec();
}#include "main.moc"
main.qml
中源码如下:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import com.example 1.0Window {visible: truewidth: 640height: 480title: qsTr("Hello World")function onTest(str) {console.log("onTest from C++:", str)}Button {text: "Send Int to C++"onClicked: backend.receiveInt("111") // 发送int到C++}}
三、参考链接
- QT6中绘制UI的两种技术详解与示例展示:https://blog.csdn.net/XiaoWang_csdn/article/details/148040458
- QML与C++混合编程详解:https://blog.csdn.net/iEearth/article/details/42243553
- QtQuick 系列教程之 QML 与 C++ 交互:https://cloud.tencent.com/developer/article/1169582
- C++ 与 QML 之间进行数据交互的几种方法:https://www.cnblogs.com/jzcn/p/17774676.html
- QML和C++信号与槽:https://blog.csdn.net/Path_of_programm/article/details/146600889
- 简单谈谈为什么QML和CPP的信号链接参数数据类型要使用QVariant:https://blog.csdn.net/manyoudian/article/details/141404951