我创建了一个最小的工作示例。我希望这是可以理解的。我的问题是,我无法为顶级商品创建模型以进一步访问商品。这是类对象体系结构的样子:
CTop
x times CMiddle
y times CBottom
这是树结构。这是代码:
CBottom.h:
#ifndef CBOTTOM_H
#define CBOTTOM_H
#include <QObject>
#include <QtQml>
class CBottom : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
CBottom(QObject *parent = nullptr) : QObject(parent)
{
}
CBottom(const QString& name, QObject *parent = nullptr) : QObject(parent)
{
qmlRegisterType<CBottom>("Bottom", 1, 0, "Bottom");
m_name = name;
}
QString name()
{
return m_name;
}
void setName(const QString& name)
{
if (name != m_name)
{
m_name = name;
emit nameChanged();
}
}
signals:
void nameChanged();
private:
QString m_name;
};
#endif // CBOTTOM_H
CMiddle.h:
#ifndef CMIDDLE_H
#define CMIDDLE_H
#include <QObject>
#include <QtQml>
#include <QVector>
#include "cbottom.h"
class CMiddle : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
CMiddle(QObject *parent = nullptr) : QObject(parent)
{
}
CMiddle(const QString& name, const QStringList& bottoms, QObject *parent = nullptr) : QObject(parent)
{
qmlRegisterType<CMiddle>("Middle", 1, 0, "Middle");
m_name = name;
foreach (auto bottom, bottoms)
{
m_bottoms.append(new CBottom(bottom));
}
}
QString name()
{
return m_name;
}
void setName(const QString& name)
{
if (name != m_name)
{
m_name = name;
emit nameChanged();
}
}
signals:
void nameChanged();
private:
QString m_name;
QVector<CBottom*> m_bottoms;
};
#endif // CMIDDLE_H
CTop.h:
#ifndef CTOP_H
#define CTOP_H
#include <QObject>
#include <QtQml>
#include "cmiddle.h"
class CTop : public QObject
{
Q_OBJECT
public:
CTop(QObject *parent = nullptr) : QObject(parent)
{
}
CTop(const QStringList& middles, QObject *parent = nullptr) : QObject(parent)
{
qmlRegisterType<CTop>("Top", 1, 0, "Top");
int i = 0;
foreach (auto middle, middles)
{
QStringList bottoms;
bottoms.append("A" + QString(i));
bottoms.append("B" + QString(i));
bottoms.append("C" + QString(i));
i++;
m_middles.append(new CMiddle(middle, bottoms));
}
}
Q_INVOKABLE QVector<CMiddle*>& middles()
{
return m_middles;
}
Q_INVOKABLE CMiddle* middle(const int index)
{
return m_middles[index];
}
private:
QVector<CMiddle*> m_middles;
};
#endif // CTOP_H
main.c:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QString>
#include <QVector>
#include <QStringList>
#include <QVariant>
#include <QQmlContext>
#include "ctop.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QStringList middles;
middles.append("FirstMiddle");
middles.append("SecondMiddle");
CTop* top = new CTop(middles);
QQmlApplicationEngine engine;
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("theTop", QVariant::fromValue(top));
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml:
import QtQuick 2.9
import QtQuick.Window 2.2
import Top 1.0
Window
{
width: 600
height: 400
visible: true
Repeater
{
model: theTop.middles();
delegate: txtComp;
}
Component
{
id: txtComp;
Text
{
text: name;
}
}
}
问题是:为什么QML代码中没有显示CMiddle
对象之一的名称?我想从导出到QML的CMiddle
组件中获取CTop
组件(作为模型)。如果此代码有效,那么我将进一步研究并建立另一个模型来访问每个CBottom
对象中的CMiddle
对象。
例如,我注意到此QML代码有效:
import QtQuick 2.9
import QtQuick.Window 2.2
import Top 1.0
Window
{
width: 600
height: 400
visible: true
Repeater
{
model: theTop;
delegate: txtComp;
}
Component
{
id: txtComp;
Text
{
text: middle(0).name;
}
}
}
这没有多大意义,但表明CTop
组件已正确暴露给QML部件。
为什么Qvector
指针的输出CMiddle
在QML部分中不能充当模型?
答案 0 :(得分:1)
QML不知道QList<CMiddle *>
,而应该使用QList<QObject *>
:
CTop.h
// ...
Q_INVOKABLE QList<QObject*> middles(){
QList<QObject*> objects;
for(CMiddle *m : qAsConst(m_middles)){
objects << m;
}
return objects;
}
// ...
另一个错误是top不一定是指针,并且由于它是QVariant::fromValue()
,因此可以不使用QObject
来传递它:
main.cpp
// ...
CTop top(middles);
QQmlApplicationEngine engine;
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("theTop", &top);
也可以在中继器中使用modelData获取模型的项目:
main.qml
//...
Component{
id: txtComp;
Text{
text: modelData.name
}
}
//...
可以找到完整的项目here