- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想知道是否有任何宏或方法如何将 Qt 模型注册为 QObject 的属性。
例如,我有 AnimalModel
( http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html#qabstractitemmodel )。
我知道我可以将它传递给 QuickView 的根上下文
QuickView view;
view.rootContext()->setContextProperty("myModel", &model);
如果我通过 Qml 宏注册了 QObject,我也可以传递这个对象来查看:
view.rootContext()->setContextProperty("obj", pDataObject);
但是如果我想拥有包含任何数据模型的 QObject 怎么办?
例如:
class DataObject : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
...
AnimalModel m_modelAnimals;
//Is this possible in any way?
//Q_PROPERTY(AnimalModel modelAnimals READ modelAnimals NOTIFY modelAnimalsChanged)
};
到目前为止,我发现的每个示例都展示了如何将 QAbstractListModel
传递给根上下文。但是没有人知道如何将它用作 QObject 属性。
(我知道有QQmlListProperty
但是QQmlListProperty
不支持部分刷新,总是需要重建所有Qml对象)
最佳答案
//Is this possible in any way?
//Q_PROPERTY(AnimalModel modelAnimals READ modelAnimals NOTIFY modelAnimalsChanged)
是的,你没有试过吗?当然,它不会是AnimalModel
。但是一个AnimalModel *
, 但只要模型继承 QAbstractListModel
,这就是你所需要的。你甚至不需要 NOTIFY
部分,随着变化,模型内部无论如何都会自动反射(reflect)出来。 modelAnimalsChanged
只有当您用不同的模型替换整个模型时才有意义,自然地,关闭 QML 关于在没有通知信号的情况下使用属性的警告。当模型对象没有改变时,一种更简洁的方法是返回一个 AnimalModel *
。来自插槽或 Q_INVOKABLE
.
如果你想要一个真正灵活的模型,你可以制作一个存储 QObject *
的模型,然后您可以从 QML 创建具有任意属性的任意对象,并将其添加到模型中。然后从模型中你有一个 object
返回对象的角色,您可以查询和使用该对象来检索它所拥有的属性。尽管“经典”列表模型实现将定义具有静态、固定模式的模型,但使用这种方法允许在模型中包含具有不同属性的“无定形”对象。
当然,这需要一些类型安全,例如 property int type
对于此类模型中的每个对象,您可以根据它确定该对象的可用属性。我通常的方法是有一个 Loader
对于委托(delegate),并将对象作为数据源传递给不同的 QML UI 实现,以可视化它实例化的对象类型。这样,您在模型中既有不同的对象,又有不同的 QML 项作为 View 委托(delegate)。
制作最终“万事通”列表/模型对象的最后一步是实现 QQmlListProperty
和 Q_CLASSINFO("DefaultProperty", "container")
为此,您可以动态地组合列表/模型,或使用 QML 的声明性语法。另请注意,使用此解决方案,您可以向此类模型添加或从中删除,甚至删除以声明方式实例化的对象。
此外,根据您的使用场景,您可能需要 qmlRegisterType()
或 qmlRegisterUncreatableType()
对于模型。
好吧,乍一看,“任何数据的模型”似乎并不是指无模式模型,而只是不同的模式模型。在那种情况下,而不是返回 AnimalModel *
, 你可以使用 QAbstractListModel *
甚至是 QObject *
- 它无论如何都可以在 QML 中工作,因为它通过元系统使用了动态性。但无论如何,无模式模型更加强大和灵活,而且它们不需要定义 C++ 代码,它可以单独从 QML 运行。
class List : public QAbstractListModel {
Q_OBJECT
QList<QObject *> _data;
Q_PROPERTY(int size READ size NOTIFY sizeChanged)
Q_PROPERTY(QQmlListProperty<QObject> content READ content)
Q_PROPERTY(QObject * parent READ parent WRITE setParent)
Q_CLASSINFO("DefaultProperty", "content")
public:
List(QObject *parent = 0) : QAbstractListModel(parent) { }
int rowCount(const QModelIndex &p) const { Q_UNUSED(p) return _data.size(); }
QVariant data(const QModelIndex &index, int role) const {
Q_UNUSED(role)
return QVariant::fromValue(_data[index.row()]);
}
QHash<int, QByteArray> roleNames() const {
static QHash<int, QByteArray> roles = { { Qt::UserRole + 1, "object" } };
return roles;
}
int size() const { return _data.size(); }
QQmlListProperty<QObject> content() { return QQmlListProperty<QObject>(this, _data); }
public slots:
void add(QObject * o) { insert(o, _data.size()); }
void insert(QObject * o, int i) {
if (i < 0 || i > _data.size()) i = _data.size();
beginInsertRows(QModelIndex(), i, i);
_data.insert(i, o);
o->setParent(this);
sizeChanged();
endInsertRows();
}
QObject * take(int i) {
if ((i > -1) && (i < _data.size())) {
beginRemoveRows(QModelIndex(), i, i);
QObject * o = _data.takeAt(i);
o->setParent(0);
sizeChanged();
endRemoveRows();
return o;
} else qDebug() << "ERROR: take() failed - object out of bounds!";
return 0;
}
QObject * get(int i) {
if ((i > -1) && (i < _data.size())) return _data[i];
else qDebug() << "ERROR: get() failed - object out of bounds!";
return 0;
}
void internalChange(QObject * o) { // added to force sort/filter reevaluation
int i = _data.indexOf(o);
if (i == -1) {
qDebug() << "internal change failed, obj not found";
return;
} else {
dataChanged(index(i), index(i));
}
}
signals:
void sizeChanged();
};
然后,在你之后qmlRegisterType<List>("Core", 1, 0, "List");
您几乎可以随心所欲地使用它 - 它可以容纳任何 QObject
或派生,自然包括 QMLs QtObject
可直接作为模型驱动ListView
.您可以使用插槽或声明动态填充它,如下所示:
List {
QtObject { ... }
QtObject { ... }
List {
QtObject { ... }
QtObject { ... }
}
}
它还将处理对象所有权,您可以轻松地嵌套它,本质上生成一个分隔的树模型 - 请注意,您不能使用 QML 的 ListModel
以声明方式执行此操作.您可能想添加 parentChanged
如果您想绑定(bind)不断变化的 parent ,则发出信号并实现发射它的 setter,在我的情况下没有必要。
关于如何在 View 中使用它,您可以使用 objectName
属性(property)或int type
属性或基本上任何区分不同对象类型的方法,并使用 Loader
对于代表:
Loader {
// using component in order to capture context props and present to the variable delegate
sourceComponent: Qt.createComponent(obj.objectName + ".qml")
// if that is not needed simply use
// source: obj.objectName + ".qml"
// or setSource to pass specific properties to delegate properties
// Component.onCompleted: setSource(obj.objectName + ".qml", {/*prop list*/})
}
更新:
Here is also the gist of the implementation一个简单且同样动态和通用的排序和过滤代理与此模型一起使用以增强可用性。
关于c++ - 如何创建用于 QML 的通用对象模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35160909/
我的一位教授给了我们一些考试练习题,其中一个问题类似于下面(伪代码): a.setColor(blue); b.setColor(red); a = b; b.setColor(purple); b
我似乎经常使用这个测试 if( object && object !== "null" && object !== "undefined" ){ doSomething(); } 在对象上,我
C# Object/object 是值类型还是引用类型? 我检查过它们可以保留引用,但是这个引用不能用于更改对象。 using System; class MyClass { public s
我在通过 AJAX 发送 json 时遇到问题。 var data = [{"name": "Will", "surname": "Smith", "age": "40"},{"name": "Wil
当我尝试访问我的 View 中的对象 {{result}} 时(我从 Express js 服务器发送该对象),它只显示 [object][object]有谁知道如何获取 JSON 格式的值吗? 这是
我有不同类型的数据(可能是字符串、整数......)。这是一个简单的例子: public static void main(String[] args) { before("one"); }
嗨,我是 json 和 javascript 的新手。 我在这个网站找到了使用json数据作为表格的方法。 我很好奇为什么当我尝试使用 json 数据作为表时,我得到 [Object,Object]
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我听别人说 null == object 比 object == null check 例如: void m1(Object obj ) { if(null == obj) // Is thi
Match 对象 提供了对正则表达式匹配的只读属性的访问。 说明 Match 对象只能通过 RegExp 对象的 Execute 方法来创建,该方法实际上返回了 Match 对象的集合。所有的
Class 对象 使用 Class 语句创建的对象。提供了对类的各种事件的访问。 说明 不允许显式地将一个变量声明为 Class 类型。在 VBScript 的上下文中,“类对象”一词指的是用
Folder 对象 提供对文件夹所有属性的访问。 说明 以下代码举例说明如何获得 Folder 对象并查看它的属性: Function ShowDateCreated(f
File 对象 提供对文件的所有属性的访问。 说明 以下代码举例说明如何获得一个 File 对象并查看它的属性: Function ShowDateCreated(fil
Drive 对象 提供对磁盘驱动器或网络共享的属性的访问。 说明 以下代码举例说明如何使用 Drive 对象访问驱动器的属性: Function ShowFreeSpac
FileSystemObject 对象 提供对计算机文件系统的访问。 说明 以下代码举例说明如何使用 FileSystemObject 对象返回一个 TextStream 对象,此对象可以被读
我是 javascript OOP 的新手,我认为这是一个相对基本的问题,但我无法通过搜索网络找到任何帮助。我是否遗漏了什么,或者我只是以错误的方式解决了这个问题? 这是我的示例代码: functio
我可以很容易地创造出很多不同的对象。例如像这样: var myObject = { myFunction: function () { return ""; } };
function Person(fname, lname) { this.fname = fname, this.lname = lname, this.getName = function()
任何人都可以向我解释为什么下面的代码给出 (object, Object) 吗? (console.log(dope) 给出了它应该的内容,但在 JSON.stringify 和 JSON.parse
我正在尝试完成散点图 exercise来自免费代码营。然而,我现在只自己学习了 d3 几个小时,在遵循 lynda.com 的教程后,我一直在尝试确定如何在工具提示中显示特定数据。 This code
我是一名优秀的程序员,十分优秀!