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控件中。