将Qt C++ 与 qml结合, 实现简单的前后端分离
使用环境
Qt 6.0 +
系统没有硬性要求, 毕竟跨平台.
但是注意, qt 6与Win10|Win11完全兼容, 与Win7较新版本兼容,
根据我现有反馈, 一些2007/2013 Win7等系统已经无法正常运行发布程序.
Windows下编译器可以选择 MSVC 2019 64bit, 可能会相对稳定 (谁会比微软更懂Windows呢)
不同qt版本, 如qt 5 与 qt 6区别较大 , 可能该方法不适用于qt5.
qt 5部分组件在qt 6中无法使用或已经弃用, 甚至一些组件已经移除, 需要自行实现.
创建项目
创建一个C++模块
- 先创建模块文件夹吧, 我将其命名为"Backend"
- 创建模块的"CMakeLists.txt" 文件
qt_add_library(backend STATIC) // 模块名称
// 这里的 Qt6 6.5 版本根据当前项目写上就好了,
// 因为需要Quick包中的组件, 所以把它添加进来吧
find_package(Qt6 6.5 REQUIRED COMPONENTS
Quick
)
set_target_properties(backend PROPERTIES
AUTOMOC ON
)
target_link_libraries(backend
PRIVATE Qt${QT_VERSION_MAJOR}::Quick
)
// 当然, 两个文件可以直接写在下方"SOURCES"中,
// 但是把它拆分为变量的话, 比较美观, 因为可能不止一种文件需要添加
// MODULE_APPQMLBACKEND_CPP_FILES是全局生效的, 所以不可重复
list(APPEND MODULE_APPQMLBACKEND_CPP_FILES
backend.h
backend.cpp
)
// URI 即包路径, import会用上
qt_add_qml_module(backend
URI Backend
VERSION 1.0
SOURCES
${MODULE_APPQMLBACKEND_CPP_FILES}
)
- 创建C++类文件, 因为在"CMakeLists.txt"中, 我将其命名为"backend", 所以:
- 在项目中引用这个新创建的模块, 找到主项目的"CMakeLists.txt", 修改其内容:
- 可以看到, 文件可以在项目中显示了
完善一个简单的C++功能吧
backend.h:
#include <QQuickItem>
#include <QDesktopServices>
#ifndef BACKEND_H
#define BACKEND_H
class Backend : public QQuickItem
{
Q_OBJECT
QML_ELEMENT // 这个宏很重要, 它决定了该类是否会被注册为一个组件
public:
Backend();
~Backend();
/*
@brief 使用默认浏览器打开一个http url
当然, 该函数在qml已经由官方实现了: Qt.openUrlExternally("your url")
此处该功能仅作演示
*/
Q_INVOKABLE void openBroswer(QString url); // 要想使一个函数被qml调用, 需要使用 Q_INVOKABLE 宏来修饰该函数
};
#endif // ~BACKEND_H
backend.cpp
#include "backend.h"
Backend::Backend()
{
}
Backend::~Backend()
{
}
void Backend::openBroswer(QString url)
{
QDesktopServices::openUrl(url);
}
当然, 编码的时候少不了代码提示:
最后, 创建一个简单的按钮界面吧
Main.qml
import QtQuick
import QtQuick.Window
import QtQuick.Controls
import Backend // 导入刚刚的Backend
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
// 创建模块对象
Backend {
id: backend
}
Pane {
id: pagePane
anchors.fill: parent
Button {
id: btnCenter
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: "Push me"
onClicked: backend.openBroswer("https://www.csdn.net/") // 在此处调用函数
}
}
}
看看效果
补充
- Backend对象会被销毁, 但是是自动的; 会调用析构函数;
- 不建议从后端返回自定义对象类型, 建议使用QJsonObject/QJsonArray替代, 在前端qml中访问JSON对象就和Web前端访问request.data对象一样使用就ok了
- 如果写代码没有编码提示, 那就先运行(Ctrl+R)一遍, 然后Clear项目, 再启动Qt Creator就有了