gpt4 book ai didi

c++ - Qt:通过点符号从 QML 访问 C++ 对象

转载 作者:行者123 更新时间:2023-11-28 05:21:52 25 4
gpt4 key购买 nike

我想通过使用方括号的点符号从 QML 访问我的应用程序的 C++ 类,例如:

myapp.object1.child_object2["key1"].grandchild_object1.property56
myapp.object2.child_object8[291045].grandchild_object4.property14

我希望能够将这些 (C++) 对象绑定(bind)到 QML 属性或在 Javascript 代码中使用它们。什么是快速而正确的方法来做到这一点?

例如,假设 MyApp 有一个 Users 对象,它是一个 QAbstractItemModel 类,它有一个用户的 QMap()。此 QMap 中的每个条目都有一个电子邮件地址作为键,以及一个包含用户属性(如电子邮件、姓名等)的 User() 对象……因此,在这种情况下,点符号为:

myapp.users["johnsmith@domain.com"].name
myapp.users["johnsmith@domain.com"].password

稍后,我会让它变得更复杂,例如为 JohnSmith 的任务添加带有 QMap() 对象的第二层层次结构:

myapp.users["johnsmith@domain.com"].tasks[1].task_name
myapp.users["johnsmith@domain.com"].tasks[2].task_name

我应该使用什么机制以HIERARCHICAL点符号形式公开我的 C++ 对象?我了解 PROPERTY 宏在 Qt 中的工作原理,但如何使它可以用于分层点符号?我应该在 QAbstractItemModel 类的子类中使用其他方法还是应该重载 [] 运算符?这可能(完全)在 QML 引擎中重载 [] 运算符吗?而且,最后一个问题,如果此时 Qt 中的层次点表示法不可行,那么通过修改源代码是否难以实现?

到目前为止,这是我的源代码:

// File: main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "myapp.h"
#include "users.h"
#include "user.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);

qmlRegisterType<MyApp>("com.myapp",1,0,"MyApp");
qmlRegisterType<Users>("com.myapp.users",1,0,"Users");
qmlRegisterType<User>("com.myapp.user",1,0,"User");

QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));

return app.exec();
}

MyApp 类。 header :

//File: myapp.h


#ifndef MYAPP_H
#define MYAPP_H

#include <QObject>
#include <QQmlListProperty>
#include "users.h"

class MyApp : public QObject
{
Q_OBJECT
Q_PROPERTY(Users *users READ get_users WRITE set_users NOTIFY usersChanged);
private:
Users m_users;
public:
explicit MyApp(QObject *parent = 0);
Q_INVOKABLE Users *get_users();
void set_users(Users *data);
signals:
void usersChanged();
};
#endif // MYAPP_H

C 源代码:

//File: myapp.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "myapp.h"
#include "users.h"
#include "user.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);

qmlRegisterType<MyApp>("com.myapp",1,0,"MyApp");
qmlRegisterType<Users>("com.myapp.users",1,0,"Users");
qmlRegisterType<User>("com.myapp.user",1,0,"User");

QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));

return app.exec();
}

用户文件。 header :

//File: users.h

#ifndef USERS_H
#define USERS_H

#include <QObject>
#include <QAbstractItemModel>
#include <QMap>
#include "user.h"

class Users : public QAbstractItemModel
{
Q_OBJECT
enum UserRoles {
EmailRole = Qt::UserRole + 1,
NameRole,
PasswordRole
};
private:
QMap<QString,User*> users_map;
public:
explicit Users(QAbstractItemModel *parent = 0);
Q_INVOKABLE QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const;
Q_INVOKABLE QModelIndex parent(const QModelIndex &child) const;
Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const;
Q_INVOKABLE int columnCount(const QModelIndex &parent = QModelIndex()) const;
Q_INVOKABLE QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
QHash<int, QByteArray> roleNames() const;
signals:

public slots:
};
#endif // USERS_H

来源:

//File: users.cpp
#include <QDebug>
#include "users.h"

Users::Users(QAbstractItemModel *parent) : QAbstractItemModel(parent)
{
User *u;
u=new User();
u->set_email("johnsmith@domain.com");
u->set_name("John Smith");
u->set_password("123");
users_map.insert(u->get_email(),u);
u=new User();
u->set_email("juliepage@domain.com");
u->set_name("Julie Page");
u->set_password("321");
users_map.insert(u->get_email(),u);
}
QModelIndex Users::parent(const QModelIndex &child) const {
return QModelIndex();
}
QModelIndex Users::index(int row, int column,const QModelIndex &parent) const {

QList <QString> qlist;
qlist=users_map.keys();
if (row>=qlist.size()) return QModelIndex();
User *user=users_map[qlist.at(row)];
return createIndex(row,column,user);
}
int Users::rowCount(const QModelIndex &parent) const {
return users_map.size();
}
int Users::columnCount(const QModelIndex &parent) const {
return 1;
}
QVariant Users::data(const QModelIndex &index, int role) const {
int row_num;

row_num=index.row();
if (role==EmailRole) {
QList <QString> qlist;
qlist=users_map.keys();
if (row_num>=qlist.size()) return (QVariant());
return QVariant(qlist.at(row_num));
}
if (role==NameRole) {
QList <QString> qlist;
qlist=users_map.keys();
if (row_num>=qlist.size()) return (QVariant());
User *user=users_map.value(qlist.at(row_num));
return QVariant(user->get_name());
}
if (role==PasswordRole) {
QList <QString> qlist;
qlist=users_map.keys();
if (row_num>=qlist.size()) return (QVariant());
User *user=users_map[qlist.at(row_num)];
return QVariant(user->get_password());
}
if (role==Qt::DisplayRole) {
return(QVariant());
}
return (QVariant());
}
QHash<int, QByteArray> Users::roleNames() const {
QHash<int, QByteArray> roles;
roles[EmailRole] = "email";
roles[NameRole] = "name";
roles[PasswordRole] = "password";
return roles;
}

用户文件。 header :

//File user.h
#ifndef USER_H
#define USER_H

#include <QObject>

class User : public QObject
{
Q_OBJECT
Q_PROPERTY(QString email READ get_email WRITE set_email NOTIFY emailChanged);
Q_PROPERTY(QString name READ get_name WRITE set_name NOTIFY nameChanged);
Q_PROPERTY(QString password READ get_password WRITE set_password NOTIFY passwordChanged);
private:
QString email;
QString name;
QString password;
public:
explicit User(QObject *parent = 0);
const QString get_email();
void set_email(QString data);
const QString get_name();
void set_name(QString data);
const QString get_password();
void set_password(QString data);
signals:
void emailChanged();
void nameChanged();
void passwordChanged();
};
#endif // USER_H

来源:

//File: user.cpp

#include "user.h"

User::User(QObject *parent) : QObject(parent)
{

}
const QString User::get_email() {
return email;
}
void User::set_email(QString data) {
if (email!=data) {
email=data;
emit emailChanged();
}
}
const QString User::get_name() {
return name;
}
void User::set_name(QString data) {
if (name!=data) {
name=data;
emit nameChanged();
}
}
const QString User::get_password() {
return password;
}
void User::set_password(QString data) {
if (password!=data) {
password=data;
emit passwordChanged();
}
}

QML 文件。

//File: main.qml

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

import com.myapp 1.0;
import com.myapp.users 1.0;
import com.myapp.user 1.0;

ApplicationWindow {
visible: true; width:640; height: 480;
MyApp {
id:myapp
}
ListView {
model: myapp.users
width: 300; height: 300
delegate: ItemDelegate {
Text {
text: model.email
}
}
}
Component.onCompleted: {
var users=myapp.users;
var user=users["johnsmith@domain.com"];
console.log("users object=" + users);
console.log("user object=" + user);
console.log("user's name="+user.name);
}
}

项目文件。 //文件:QML1.pro

QT += qml quick

CONFIG += c++11

SOURCES += main.cpp \
myapp.cpp \
users.cpp \
user.cpp

RESOURCES += qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Default rules for deployment.
include(deployment.pri)

HEADERS += \
myapp.h \
users.h \
user.h

以及当我运行程序时的调试输出:

qml: users object=Users(0x15cd1b0)
qml: user object=undefined
qrc:/main.qml:28: TypeError: Cannot read property 'name' of undefined

如您所见,我无法超出 [] 方括号点,QML 未检索到 User 对象。

最佳答案

您不能对 QML 中的 C++ 对象使用运算符,如果您想从 QML 中访问,则需要使用函数。如果您已经有一个带有运算符的对象,您可以编写调用运算符的函数包装器。

只要 QML 知道对象,点语法就可以工作,换句话说,它需要为它们生成元信息。因此,对象必须是 QObject 派生的,或者使用 Q_GADGET 并公开为 Q_INVOKABLE 函数或 Q_PROPERTY

在这种情况下代替:

myapp.object1.child_object2["key1"].grandchild_object1.property56

你会

//    prop    prop          invokable   prop               prop
myapp.object1.child_object2.get("key1").grandchild_object1.property56

或者如果您通过访问函数实现子对象:

myapp.object1().child_object2().get("key1").grandchild_object1().property56

更新:

请注意,对于正确实现的 QQmlListProperty,您可以使用 [] 运算符,但仅限于索引访问。而且您不能直接从对象执行此操作,您必须从对象的列表属性执行此操作,例如 object.listProperty[index]。我注意到即使您在代码中包含 QQmlListProperty,它也没有真正实现。

因此,如果您将任务实现为 UserQQmlListProperty,那么您可以这样做:

myapp.users.get("johnsmith@domain.com").tasks[1].task_name

请确保您没有越界。您还可以使用 tasks.length 来避免这种情况。

我不知道这是如何实现的,但是 QQmlListProperty 本身和关联的类型没有实现 [] 运算符。我的猜测是这是在 QML 引擎级别上实现的,并且可能不是公共(public) API 的一部分或直接可供使用,这对于 Qt 内部结构来说是很典型的。

关于c++ - Qt:通过点符号从 QML 访问 C++ 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41335772/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com