qml: 属性设置 Q_PROPERTY 【重点】
2025-08-10 本文已影响0人
xqiiitan
qml属性设置,QPROPERTY.png
cpp 扩展qml类型。
//cpptype.h
#ifndef CPPTYPE_H
#define CPPTYPE_H
#include <QObject>
#include <QQmlEngine>
#include "QDebug"
class CppType : public QObject
{
Q_OBJECT
// QML_ELEMENT;
public:
explicit CppType(QObject *parent = nullptr);
Q_INVOKABLE void greet() { qDebug() << "Hello from C++!"; }
signals:
public slots:
};
#endif // CPPTYPE_H
//cpptype.cpp
#include "cpptype.h"
CppType::CppType(QObject *parent) : QObject{parent}
{
qDebug() << "create cppType 7878";
}
#include "cpptype.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
//将自定义cpp 注册成QML组件
qmlRegisterType<CppType>("com.example", 1, 0, "CppType");
//...
}
//main.qml 使用
import com.example 1.0 //导入注册的qml组件。
Window{
id:root
visible: true
width: 640
height: 480
//cpp 扩展qml的类型。
CppType {
Component.onCompleted: greet()
}
}
2.属性设置 Q_PROPERTY 【重点】
//cpptype.h
#ifndef CPPTYPE_H
#define CPPTYPE_H
#include <QObject>
#include <QQmlEngine>
#include "QDebug"
//自定义qml组件 CppType.
class CppType : public QObject
{
Q_OBJECT
//属性name,可读name 可写setName.REQUIRED Qt6.2+版本才有。
//修改属性触发信号nameChanged
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
//成员变量MENBER m_url, 声明QString类型的变量url.
Q_PROPERTY(QString url MEMBER m_url READ url WRITE setUrl NOTIFY urlChanged)
// QML_ELEMENT;
public:
explicit CppType(QObject *parent = nullptr);
//访问cpp的方法,打印内容.
Q_INVOKABLE void greet() { qDebug() << "Hello from C++!"; }
//2.访问name,返回CppType设置的objectName.
QString name() { return objectName();}
void setName(QString name) { //内联函数,在.h中实现
//2.1 内容修改了,才触发信号.
if(name == objectName()) return;
setObjectName(name);//2.2 设置新的属性
emit nameChanged(); //2.3 手动触发信号
}
//getter,setter方法。
QString url() const {return m_url;}
void setUrl(const QString &newUrl){
//可在此处添加url合法的验证,不合法直接return.
if (newUrl != m_url) { //内容修改了,才触发信号.
m_url = newUrl;
emit urlChanged(); //发信号(信号调用)
}
}
//无参,无返回值的函数.开放一个函数给qml调用.
Q_INVOKABLE void cppFunction()
{
qDebug() << "call cppFunction";
emit played(); //发送信号,触发CppType的onPlayed
}
//传递3种类型:基础、列表、js对象
Q_INVOKABLE QString getData(int index,
std::vector<int> arr,
QVariantMap maps)
{
qDebug() << "getData index:" << index;
for(auto v: arr) {//array
qDebug() << v;
}
for(auto k: maps.keys()){//map
qDebug() << k << ":"<<maps[k].toString();
}
return "getData return string";
}
signals:
void nameChanged(); //3.属性变化信号
void urlChanged();
void played(); //开始播放信号
private:
QString m_url; //成员变量
public slots:
};
#endif // CPPTYPE_H
//cpptype.cpp
#include "cpptype.h"
CppType::CppType(QObject *parent) : QObject{parent}
{
qDebug() << "create cppType 构造方法";
}
//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QScreen>
#include <QApplication>
#include <QQuickView>
#include <QQmlComponent>
#include <memory>
#include <qquickwindow.h>
#include "cpptype.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
//4.将自定义cpp 注册成QML组件
qmlRegisterType<CppType>("com.example", 1, 0, "CppType");
QQmlEngine eng;
QQmlComponent com(&eng);
com.loadUrl(QUrl("qrc:/main.qml"));
if(com.isError()) qDebug() << com.errorString();//解析代码
//auto comwin = static_cast<QQuickWindow*>(com.create());
//智能指针,用完之后,ct会自动释放.
std::unique_ptr<QQuickWindow> ct(
static_cast<QQuickWindow*>(com.create()));
if(com.isError()) qDebug() << com.errorString();//运行代码
return app.exec();
}
//main.qml
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.0
import com.example 1.0 //5.使用自定义的cpp 组件CppType
Window {
id:root
visible: true
width: 640
height: 480
title: qsTr("H1212ello World 0809 ")
Column{
//6.cpp 扩展qml的类型。
CppType {
id:cpp1
//objectName: "abcdABCD1234"
name: "myname"
url: "https://www.baidu.com" //url初始值
Component.onCompleted: greet() //调用cpp的
onNameChanged: {
print("onNameChanged: " + name);
}
onUrlChanged: {//监听URL变化,可以在这里添加 URL 验证逻辑
print("onUrlChanged: " + url);
}
onPlayed: print("onPlayed---------");
}
Button{
text: "cppType"
property int count: 0
onClicked: {
print("onClicked: " + cpp1.name);
cpp1.name = "newName clicked " + (count++);
}
}
Button{
text: "cppType change one."
onClicked: {
cpp1.name = "newName clicked!!!!";
}
}
Button{
text: "change url."
onClicked: {
console.log("读取url:" + cpp1.url);
cpp1.url = "change url. 666";
}
}
Button{
property int count: 0
text: "change url.count"
onClicked: {
count++;
cpp1.url = "change url. count:" + count;//7.更新 URL 属性
console.log("读取url:" + cpp1.url);//读取 URL 属性
}
}
//------------qml: 调用cpp的函数------------
Button{
text: "cppFunction"
onClicked: {
cpp1.cppFunction();//直接调用cpp函数
}
}
Button{
text: "getData"
onClicked: {
var arr=[11,22,33,44]; //js数组
//js 的对象
var obj = {"name":"myName", "url":"myurl"};
var res = cpp1.getData(100, arr, obj); //数据传递给cpp
console.log(res); //打印方法的返回值
}
}
}
}
qml调用c++ 扩展的函数和型号并传递数组 和js对象。
Q_INVOKABLE: 将此宏应用于成员函数的声明,以允许通过元对象系统调用它们(反射)
信号触发机制详解:
1.属性修改流程:
- QML 修改 url 属性 → 调用 C++ setUrl() 方法
- setUrl() 比较新旧值 → 不同则更新并触发信号
- urlChanged() 信号触发 → QML 的 onUrlChanged 处理器执行.
2.属性绑定示例:
Text {
text: "当前URL: " + urlHandler.url
// 自动绑定,url变化时自动更新
}
3.手动触发信号(如果需要)
emit urlChanged(); // 在 C++ 中
urlHandler.urlChanged()// 在 QML 中
更多:2. 添加只读属性获取 URL 各部分
//cpp
Q_PROPERTY(QString urlDomain READ urlDomain NOTIFY urlChanged)
QString urlDomain() const {
return QUrl(m_url).host();
}
//qml
UrlHandler {
id: handler
// 计算属性获取 URL 协议
readonly property string urlProtocol: {
try {
return url.split(":")[0]
} catch(e) {
return ""
}
}
}