来自 QML 的索引处的访问列表
Posted
技术标签:
【中文标题】来自 QML 的索引处的访问列表【英文标题】:Access list at index from QML 【发布时间】:2019-04-23 08:53:37 【问题描述】:在我的程序中,我有一个需要从 QML 访问的树状对象架构。我无法弄清楚如何创建Q_PROPERTY
getter 函数,这将允许我访问我选择的索引处的项目。该函数在 C++ 部分如下所示:
/**
* @brief Risk object getter function.
* @param index: The index of the risk from the \ref m_risks container.
* @return Pointer to the risk object if \p index is valid. Otherwise 0.
*/
CRiskData* CVessel::getRisk(const int index)
if (index >= m_risks.length())
return nullptr;
return m_risks[index];
但似乎这个QML Qt属性通信系统只允许一个没有输入参数的getter。我试图这样定义它:
Q_PROPERTY(CRiskData* risk READ getRisk)
我收到一个编译器错误,找不到匹配的函数:
moc_cvessel.cpp:122: error: no matching function for call to 'CVessel::getRisk()'
case 0: *reinterpret_cast< CRiskData**>(_v) = _t->getRisk(); break;
^
所以 MOC 创建了没有输入参数的函数... 有没有办法解决?目标是能够以分层方式从 QML 端访问对象的每个元素。
【问题讨论】:
您可以使用Q_INVOKABLE
使其成为一个可以有参数的函数,但是,这对于绑定而言可能并不方便,但由于没有给出那部分代码,因此无法检查
@Amfasis 谢谢你的回答。我认为这会奏效,会尝试实施。
【参考方案1】:
看看你的问题,我认为你应该使用与 MVVM (https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel) 或 MVC 相关的东西。因此,您应该通过子类化QAbstractItemModel
,创建您自己的 C++ 模型并暴露给 QML。在此模型中,在您的列表模型中创建一个Q_INVOKABLE
方法:
cvessel.hpp:
#ifndef CVESSEL_HPP
#define CVESSEL_HPP
#include <QAbstractItemModel>
#include <QList>
class CRiskData;
class CVessel: public QAbstractItemModel
Q_OBJECT
public:
CVessel(QObject * parent = nullptr);
Q_INVOKABLE CRiskData* getRisk(const int index);
static void declareQML();
// QAbstractItemModel subclassing & rest of the header
protected:
QList<CRiskData *> m_risks;
;
#endif // CVESSEL_HPP
cvessel.cpp:
#include "cvessel.hpp"
#include <QQmlEngine>
#include "criskdata.hpp"
CVessel::CVessel(QObject * parent = nullptr) :
QAbstractItemModel(parent),
m_risks()
CRiskData* CVessel::getRisk(const int index);
if (index >= m_risks.length())
return nullptr;
return m_risks[index];
void CVessel::declareQML()
qmlRegisterType<CVessel>("Bremen", 3, 14, "CVessel");
// Rest of implementation
RiskComponent.qml:
import QtQuick 2.12
import Bremen 3.14
Item
id: risk_component
// ...
TreeItem
id: the_tree
model: CVessel
// ...
// ...
function usingARisk(riskIndex)
var risk = risk_component.the_tree.model.getRisk(riskIndex)
// Using your risk on the QML side. For Example:
console.log(qsTr("Risk level: %1").arg(risk.level))
// ...
main.cpp:
#include <QApplication>
#include <QQmlApplicationEngine>
#include "criskdata.hpp"
#include "cvessel.hpp"
int main(int argc, char ** argv)
QApplication app(argc, argv);
//...
CRiskData::declareQML(); // Of course if you use it on the QML side.
CVessel::declareQML();
//...
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
int res = engine.rootObjects().isEmpty() ? -1 : app.exec();
//...
return res;
有关模型子类化的更多信息,请查看 Qt 文档中的 the "Model/View Programming" page,尤其是 the "Model Subclassing Reference" section。
【讨论】:
你为什么在这里继承QAbstractItemModel
?有必要吗?
我刚刚更新了我对您的评论问题的回答。
感谢您的更新。我的观点是,“to qml”曝光功能可以通过仅使用 Qobject 来实现。这就是为什么我问为什么要这样做。
对于“to QML”暴露,您必须:1°)子类QObject
,2°)提供默认构造函数和3°)在main();
入口点调用qmlRegisterType<>();
.欲了解更多信息,请查看:doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html
没错!这就是为什么我想知道最后使用了 QAbstra tItemModel 吗?以上是关于来自 QML 的索引处的访问列表的主要内容,如果未能解决你的问题,请参考以下文章
如何从 QML 中的列表视图访问 currentItem 的角色?