- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想通过使用方括号的点符号从 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
,它也没有真正实现。
因此,如果您将任务实现为 User
的 QQmlListProperty
,那么您可以这样做:
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/
如果下一个元素的宽度超过指定布局的宽度,是否有 QML 布局或某些配置会自动将 QML 项目包装到下一行? 当我使用 QML GridLayout ,项目刚好离开窗口的边缘并被剪裁: GridLayo
如果下一个元素的宽度超过指定布局的宽度,是否有 QML 布局或某些配置会自动将 QML 项目包装到下一行? 当我使用 QML GridLayout ,项目刚好离开窗口的边缘并被剪裁: GridLayo
如何在 qml 文件之间发送变量或信号? http://i.stack.imgur.com/MChCG.png Mainwindow -> 创建组件Item2.qml MainWindow -> 创建
我正在做一些事情,我有一个名为“FloatingMenu”的类(它应该在 C++ 中管理菜单)及其在文件 FloatingMenu.qml 中用于 GUI 的 QML alter-ego。我有一个文件
我正在尝试做一些看似简单的事情,但失败了:定义一个简单的内联文本格式组件,然后用不同的文本多次实例化它。这是代码 Item { . . . Component { id: favButtonL
我可以在页面中使用 InvokeActionItem 轻松共享项目,但我需要能够在 ListView 项目中调用它。我设法触发了一个调用,但我不知道如何在触发它时添加数据。我不断收到错误消息 Invo
我如何在 QML 中检测 Window {} 之外的点击? Rectangle { id: topLevel height: 400; width: 400 Window {
我试过 : var child = grid.children[slot1]; grid.children[slot1] = grid.children[slot2]; grid.children[s
例如,我希望创建一个包含 100 个文本编辑器的 qml 窗口,如何在循环中创建它?那可能吗? 最佳答案 循环是命令式代码,所以它不是 QML,而是 Javascript 或 C++。所以当然,你可以
这是我的 QML 文件,其中包含一个文本组件: import QtQuick 2.0 Item { id: idItmWrapText Text { id: idTxt
我正在寻找一种方法来显示一个文本提示,说明预期的输入作为对用户的建议。以谷歌搜索栏为例: 是否有我缺少的属性,或者这是必须通过脚本来实现的? 最佳答案 Qt Quick 输入项上不存在该属性。您可以为
为 qml 项设置背景的最简单方法是让子矩形的 anchor 完全填满父项: Item { width: 320 height: 240 Rectangle {
我想将属性动态添加到 QML 元素: Item { id: dynamicProperty; property int first; Component.onCompleted: { /*
我用 PySide 和 QML 编写了某种安装程序。按照设计,它必须是多页的。而且我想将要从 QML 表单调用的插槽划分为不同的对象(理想情况下,划分为模块,但据我了解,带有插槽的对象必须继承 QOb
QML 中有没有办法用 opacity: 0 创建一个矩形?仍然有可见的边界?如果没有,有关如何解决它的任何建议? 谢谢 最佳答案 不,不透明度适用于项目的完整视觉方面(并且不透明度:0 使项目完全不
属性变体 a:{}似乎不起作用。 a 最终未定义,而不是一个空字典。 我对 Javascript 不是很有经验...初始化属性以保存空字典的正确方法是什么? 以下 qml 在控制台上打印“qrc:/m
我在 SO 上查看了大量关于 QML 内容边距的问题,但所有答案都指向缺少 spacing: 0 属性。我已经完成了所有这些,但仍然有一些我无法消除的奇怪空间。任何人都可以解释为什么这个 QML 代码
我有一个用于样式定义的 QML 单例,定义如下: pragma Singleton import QtQuick 2.2 import QtQuick.Controls 1.1 import QtQu
这是以下代码的结果: 主.qml import QtQuick 2.8 Item { Reusable { index: 1234 // reusable with
属性变体 a:{}似乎不起作用。 a 最终未定义,而不是一个空字典。 我对 Javascript 不是很有经验...初始化属性以保存空字典的正确方法是什么? 以下 qml 在控制台上打印“qrc:/m
我是一名优秀的程序员,十分优秀!