Qt 你好 | 专注于Qt的技术分享平台
QML写界面,业务逻辑使用C++,既能快速的开发界面也能利用C++的强大生态,这是目前比较被认可的方式,那就涉及到QML与C++对象的交互。
我们以登录例子来说明,页面点击登录,将信息传递到c++ http对象进行密码的验证,然后返回登录结果。
一,调用C++中的函数
1,普通C++类
#ifndef HTTPHANDLER_H #define HTTPHANDLER_H #include <QObject> class HTTPHandler:public QObject{ Q_OBJECT public: HTTPHandler(QObject* parent=0):QObject(parent){ } //登录接口 验证用户名 和密码 Q_INVOKABLE bool login(QString name,QString pwd){ if(name=="admin"&&pwd=="123"){ return true; }else{ return false; } } }; #endif // HTTPHANDLER_H
2,注册C++ 类
main.cpp注册此 C++ 类型,这样QML中就能使用了。
#include <QGuiApplication> #include <QQmlApplicationEngine> #include "HTTPHandler.h" int main(int argc, char *argv[]) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QGuiApplication app(argc, argv); //注册类型 qmlRegisterType<HTTPHandler>("HTTPHandler", 1, 0, "HTTPHandler"); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); 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(); }
3,调用C++对象中的函数
只要是C++中 通过Q_INVOKABLE关键词声明的public函数,QML中都能访问。
import QtQuick 2.15 import QtQuick.Controls 1.4 //导入C++ 对象 import HTTPHandler 1.0 Rectangle{ width: 200 height: 200 //相当于 实列化一个C++对象 HTTPHandler{ id:httpHandler } signal loginOk() Row{ anchors.centerIn: parent TextField{ id:name } TextField{ id:pwd } } Button{ anchors.bottom: parent.bottom text: qsTr("登录") onClicked: { //调用C++对象中的函数 if(httpHandler.login(name.text,pwd.text)){ loginOk() } } } }
二,响应C++中的信号
上述方式相当于同步的方式调用C++中的函数,还可以异步的响应C++中的信号,相当于QML中的槽与C++中的信号进行绑定。
1,C++类
#ifndef HTTPHANDLER_H #define HTTPHANDLER_H #include <QObject> class HTTPHandler:public QObject{ Q_OBJECT public: HTTPHandler(QObject* parent=0):QObject(parent){ } Q_INVOKABLE void login(QString name,QString pwd){ if(name=="admin"&&pwd=="123"){ //验证成功后 激发信号 emit loginSuccess(); } } signals: //登录成功信号 void loginSuccess(); }; #endif // HTTPHANDLER_H
2,响应C++信号
import QtQuick 2.15 import QtQuick.Controls 1.4 import HTTPHandler 1.0 Rectangle{ width: 200 height: 200 //相当于 实列化一个C++对象 HTTPHandler{ id:httpHandler //绑定C++信号 onLoginSuccess: { loginOk() } } signal loginOk() Row{ anchors.centerIn: parent TextField{ id:name } TextField{ id:pwd } } Button{ anchors.bottom: parent.bottom text: qsTr("登录") onClicked: { //调用C++对象中的函数 httpHandler.login(name.text,pwd.text) } } }
三,绑定C++中的属性
还可以直接在C++定义属性,然后QML绑定此属性,适合实时的传递一些状态数据。
1,C++类
#ifndef HTTPHANDLER_H #define HTTPHANDLER_H #include <QObject> class HTTPHandler:public QObject{ Q_OBJECT //注册属性 Q_PROPERTY(QString status READ getStatus WRITE setStatus NOTIFY statusChanged FINAL) public: HTTPHandler(QObject* parent=0):QObject(parent){ } Q_INVOKABLE bool login(QString name,QString pwd){ if(name=="admin"&&pwd=="123"){ return true; }else{ //设置状态信息 setStatus("pwd or name error"); } } QString getStatus() const; void setStatus(const QString &newStatus); signals: void statusChanged(); private: //状态信息 QString status; }; inline QString HTTPHandler::getStatus() const { return status; } inline void HTTPHandler::setStatus(const QString &newStatus) { if (status == newStatus) return; status = newStatus; emit statusChanged(); } #endif // HTTPHANDLER_H
2,绑定属性
import QtQuick 2.15 import QtQuick.Controls 1.4 import HTTPHandler 1.0 Rectangle{ width: 200 height: 200 //相当于 实列化一个C++对象 HTTPHandler{ id:httpHandler } signal loginOk() Row{ anchors.centerIn: parent TextField{ id:name } TextField{ id:pwd } } //定义一个文本框 直接绑定C++的属性 Text { anchors.top: parent.top text: httpHandler.status } Button{ anchors.bottom: parent.bottom text: qsTr("登录") onClicked: { //调用C++对象中的函数 if(httpHandler.login(name.text,pwd.text)){ loginOk() } } } }
3,看下效果
点击登录 ,如果密码或用户名错误会将C++的状态信息,实时的显示到左上角的QML Text控件中。来这里看(QML与C++交互 | Qt 你好)