Qt6:QML Listview访问C++模型时的警告

问题描述 投票:0回答:1

首先,我是 Qt6 和 QML 的新手,所以也许我遗漏了一些明显的东西。

我正在尝试从

QObject
属性将 C++ 模型链接到 QML 中的 ListView。
this doc 我应该能够在 QML 视图中使用
List<QObject*>
作为静态模型。

但是,在该示例中,

QList<QObject*>
直接传递给
QQuickView

我想从
QObject
的属性访问对象列表,我已经可以在 QML 中访问。
但是当我尝试这样做时,列表视图中没有显示任何内容,我不知道我做错了什么......
另外,QML 向我报告警告(请参阅下面的示例代码)。

这是我想要实现的目标的最小工作示例:

后端.h

#ifndef BACKEND_H
#define BACKEND_H

#include <QObject>

// Contains the data I want to display for each element
class Item : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name MEMBER m_name NOTIFY onNameChanged)

public:
    Item(QString name, QObject *parent = nullptr)
        : QObject{parent}, m_name(name)
    {}

signals:
    void onNameChanged();

private:
    QString m_name {"NULL"};
};

// This class contains the model I want to display.
// The data will be loaded before loading the QML file.
// It can be switched between a mockup and a real backend depending on the context.
class Backend : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString header MEMBER m_header NOTIFY onHeaderChanged)
    Q_PROPERTY(QList<QObject*> model MEMBER m_model NOTIFY onModelChanged)

public:
    explicit Backend(QObject *parent = nullptr)
        : QObject{parent}
    {
        m_header = "Cpp Backend";
        m_model.append(new Item {"Cpp"});
        m_model.append(new Item {"backend"});
        m_model.append(new Item {"is"});
        m_model.append(new Item {"great!"});
    }

    virtual ~Backend() override
    {
        for (QObject* item : m_model)
            delete item;
    }

signals:
    void onHeaderChanged();
    void onModelChanged();

private:
    QString m_header;
    QList<QObject*> m_model;
};

#endif // BACKEND_H

主.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQMLContext>

#include "backend.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    // Exposing the backend to QML with the name "cppBackend"
    Backend backend;
    engine.rootContext()->setContextProperty("cppBackend", &backend);

    const QUrl url(u"qrc:/TestBackend/Main.qml"_qs);
    QObject::connect(
        &engine,
        &QQmlApplicationEngine::objectCreationFailed,
        &app,
        []() { QCoreApplication::exit(-1); },
        Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

主要.qml

import QtQuick

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    ListModel {
        id: mockupList
        ListElement { name: "Hello" }
        ListElement { name: "World!" }
        ListElement { name: "How" }
        ListElement { name: "are" }
        ListElement { name: "you?" }
    }

    ListView {
        id: listView
        anchors.fill: parent
        anchors.margins: 20
        spacing: 10
        orientation: ListView.Vertical

        //model: mockupList // this works as expected
        model: cppBackend.model // this doesn't show anything in the listview

        delegate: Item {
            id: myItem
            required property string name

            width: label.width
            height: label.height
            Text {
                id: label
                text: myItem.name
                font.pointSize: 24
            }
        }

        header: Text {
            width: parent.width
            horizontalAlignment: Text.AlignHCenter
            font.pointSize: 48
            font.bold: true

            text: cppBackend.header // This works as expected
        }
    }
}

当我使用 te

mockupList
而不是 C++ 后端时,项目会按预期显示。
但是,当使用
cppBackend
时,我收到此警告:

qrc:/TestBackend/Main.qml:30:13: Required property name was not initialized qrc:/TestBackend/Main.qml: 30

似乎属性

cppBackend.model
已被访问,但内部的项目不提供对其属性的访问,因为似乎应该在Qt文档中完成...

qt qml qtquick2 qt6
1个回答
0
投票

直接从 QML 公开模型效果很好,尽管通过 Q_PROPERTY 访问模型似乎由于某种原因失败。我自己不明白其中的区别,但这是我如何让它发挥作用的:

首先创建一个访问器来获取模型:

class Backend : public QObject
{
    Q_OBJECT

public:
    ...

    QList<QObject *> model() { return m_model; }
};

然后将该模型公开给 QML:

Backend backend;
engine.rootContext()->setContextProperty("cppBackendModel", QVariant::fromValue(backend.model()));

最后从 QML 访问该模型。

    ListView {
        id: listView

        model: cppBackendModel

        delegate: Item {
            id: myItem
            required property string name
            ...
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.