首页 > 解决方案 > 无法在 QML ListView 中调用 Qt c++ 方法

问题描述

我有一个 QObjects 列表作为 ListView 的 qml 模型。我可以更改它们的属性,但不能调用任何插槽或 Q_INVOKABLE 方法。这是我的问题的最小示例(遗憾的是它仍然很大)。

用一个属性和一个可调用的方法定义一个非常简单的类


    // DummyObject.h

    class DummyElem : public QObject
    {
        Q_OBJECT

        Q_PROPERTY(QString dummy READ getDummy CONSTANT)
    public:
        explicit DummyElem(QObject *parent = nullptr);

        QString getDummy();
        Q_INVOKABLE void notifyStuff();
    };
实现这个简单类的琐碎方法
    // DummyObject.cpp

    #include "DummyElem.h"
    #include <QDebug>

    DummyElem::DummyElem(QObject *parent) : QObject(parent) {}

    QString DummyElem::getDummy() {return "lorem";}
    void DummyElem::notifyStuff() {qDebug() << "ipsum";}
以列表作为根属性启动一个 qml 应用程序。完全从教程中复制粘贴,他们在其中调用了 q_incokable 方法。
    // main.cpp

    #include "DummyElem.h"

    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

        QGuiApplication app(argc, argv);

        QList<QObject*> dataList;
        dataList.append(new DummyElem);
        dataList.append(new DummyElem);

        QQmlApplicationEngine engine;
        QQmlContext* context = engine.rootContext();
        context->setContextProperty("dataModel", QVariant::fromValue(dataList));

        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

        return app.exec();
    }

用一个 ListView 和一个委托来描述一个 qml 布局,该委托将在单击时调用一个 c++ 方法。
    // main.qml

    import QtQuick 2.7
    import QtQuick.Window 2.2

    Window {
        visible: true

        ListView {
            anchors.fill: parent
            model: dataModel
            delegate: Component {
                Text {
                    text: model.dummy

                    MouseArea {
                        anchors.fill: parent
                        onClicked: {model.notifyStuff()}
                    }
                }
            }
        }
    }

这个问题很难调试,因为 C++ 类模型不能被 json-strigified,我也不能得到它的 javascript 条目()。我得到的错误是“未定义不是函数”,这也很酷。我尝试在 QML 中注册 Qt 类型,但这也没有做任何事情。

我使用的是 Qt 库版本 5.9.4,但 QtCreator 中的“所需的最小 qt 版本”框设置为“Qt 5.6”。

标签: c++qtqml

解决方案


你需要使用modelData. 我不完全确定为什么,很可能是因为QVariantList. 您可以在此页面上阅读更多内容。

Window {
    visible: true

    ListView {
        anchors.fill: parent
        model: dataModel
        delegate: Component {
            Text {
                text: modelData.dummy

                MouseArea {
                    anchors.fill: parent
                    onClicked: modelData.notifyStuff();
                }
            }
        }
    }
}

有趣的事实:这是我在 Qt 5.11.3 上遇到的错误:

TypeError: Property 'notifyStuff' of object QQmlDMObjectData(0x5585fe567650) is not a function

至少比 更能说明问题undefined,但我想说的仍然不是完全描述性的。


推荐阅读