简体   繁体   English

QList <QList <QString >>传递给QML

[英]QList<QList<QString>> passed into QML

I'm trying to pass a 2d QList as a Q_PROPERTY into QML, however, inside QML and i am unable to actually access any of the information. 我试图将2d QList作为Q_PROPERTY传递给QML,但是,在QML中,我无法实际访问任何信息。

some code: 一些代码:

c++: the q_property get populated by a q_invokable function in the constructor: c ++:q_property由构造函数中的q_invokable函数填充:

void Class::createNewGameArray(){
QList<QList<QString>> testArray;

for( int i = 0; i < _intervals.size(); ++i) {
    QList<QString> innerArray;
    testArray.append(innerArray);
        testArray[i].append(_intervals[i]);
        testArray[i].append("Audio");
}
for( int i = 0; i < _intervals.size(); ++i) {
    QList<QString> innerArray;
    testArray.append(innerArray);
        testArray[i+12].append(_intervals[i]);
        testArray[i+12].append("Text");
}
 std::random_shuffle(testArray.begin(),testArray.end());
Class::setGameArray(testArray);
emit gameArrayChanged(_newGameArray);

which returns this: 返回这个:

(("M7", "Text"), ("M3", "Text"), ("m3", "Text"), ("M6", "Audio"), ("TT", "Audio"), ("P4", "Text"), ("m7", "Audio"), ("m2", "Text"), ("m6", "Audio"), ("m6", "Text"), ("M7", "Audio"), ("P5", "Text"), ("P4", "Audio"), ("m2", "Audio"), ("M2", "Audio"), ("M3", "Audio"), ("P5", "Audio"), ("m3", "Audio"), ("M6", "Text"), ("TT", "Text"), ("m7", "Text"), ("Oct", "Audio"), ("Oct", "Text"), ("M2", "Text"))

exactly what i want. 正是我想要的。

i set the rootContext like so in main.cpp: 我在main.cpp中设置了rootContext:

Class object;

QQmlApplicationEngine engine;
QQmlContext* context = engine.rootContext();

context->setContextProperty("object", &object);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

however, inside qml i only get 但是,在qml中我只能得到

qml: QVariant(QList<QList<QString> >)

and am unable to actually do anything with it. 我无法用它做任何事情。

My goal, ideally, would be to be able to access the 2d qlist from qml in this manner: 理想情况下,我的目标是能够以这种方式从qml访问2d qlist:

object.gameArray[0][1] // return "Text" object.gameArray [0] [1] //返回“文本”

I'm able to do this with regular QLists (without the 2d). 我可以用常规QLists(没有2d)来做到这一点。 Any help would be greatly appreciated! 任何帮助将不胜感激!

QML does not inherently understand QLists, so in general it is not possible to pass in a QList of any type T and have QML able to access the items inside the list. QML本身并不理解QLists,因此通常无法传入任何类型T的QList并且QML能够访问列表中的项目。

However, the QML engine does have built in support for a few specific types of QList: 但是,QML引擎确实内置了对几种特定类型的QList的支持:

  • QList<QObject *>
  • QList<QVariant>
  • QStringList - (not QList<QString> !!!) QStringList - (不是QList<QString> !!!)

Therefore if you can construct your list of lists using any combination of the 3 types above, then you can have a working solution. 因此,如果您可以使用上述3种类型的任意组合构建列表列表,那么您可以拥有一个可行的解决方案。 In your use case I would suggest the following construction: 在您的用例中,我建议采用以下结构:

QList<QVariant(QStringList)>

A final note before we try it... Just because this will work, it does not necessarily mean that it is a good idea. 在我们尝试之前的最后一点注意事项......仅仅因为这将起作用,并不一定意味着它是一个好主意。 The QList contents are copied to Javascript arrays at runtime, and therefore any minor updates to any of the lists from the C++ will cause the entire list to be reconstructed as a new Javascript array, which could be expensive. QList内容在运行时被复制到Javascript数组,因此对C ++中任何列表的任何次要更新都会导致整个列表被重建为新的Javascript数组,这可能很昂贵。

Now, let's try it... 现在,我们来试试吧......

myclass.h myclass.h

#ifndef MYCLASS_H
#define MYCLASS_H
#include <QStringList>
#include <QVariant>

class MyClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QList<QVariant> variantList READ variantList NOTIFY variantListChanged)

public:
    explicit MyClass(QObject *parent = nullptr) : QObject(parent),
        m_variantList({
                      QStringList({ "apple", "banana", "coconut" }),
                      QStringList({ "alice", "bob", "charlie" }),
                      QStringList({ "alpha", "beta", "gamma" })
        }) { }

    QList<QVariant> variantList() const { return m_variantList; }

signals:
    void variantListChanged();

public slots:

private:
    QList<QVariant> m_variantList;
};

#endif // MYCLASS_H

main.qml main.qml

import QtQuick 2.7
import QtQuick.Controls 2.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    Column {
        id: column

        // will add the strings here from the handler below
    }

    Component.onCompleted: {
        console.log("variantList length %1".arg(myClass.variantList.length))

        for (var i = 0; i < myClass.variantList.length; i++) {

            console.log("stringList %1 length %2".arg(i).arg(myClass.variantList[i].length))

            for (var j = 0; j < myClass.variantList[i].length; j++) {
                // print strings to the console
                console.log("variantList i(%1), j(%2) = %3".arg(i).arg(j).arg(myClass.variantList[i][j]))

                // add the strings to a visual list so we can see them in the user interface
                Qt.createQmlObject('import QtQuick 2.7; Text { text: "i(%1), j(%2) = %3" }'.arg(i).arg(j).arg(myClass.variantList[i][j]), column)
            }
        }
    }
}

main.cpp main.cpp中

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "myclass.h"

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

    QQmlApplicationEngine engine;

    MyClass myClass;
    engine.rootContext()->setContextProperty("myClass", &myClass);

    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

Runtime output 运行时输出

qml: variantList length 3
qml: stringList 0 length 3
qml: variantList i(0), j(0) = apple
qml: variantList i(0), j(1) = banana
qml: variantList i(0), j(2) = coconut
qml: stringList 1 length 3
qml: variantList i(1), j(0) = alice
qml: variantList i(1), j(1) = bob
qml: variantList i(1), j(2) = charlie
qml: stringList 2 length 3
qml: variantList i(2), j(0) = alpha
qml: variantList i(2), j(1) = beta
qml: variantList i(2), j(2) = gamma

视觉输出

... and it works :) ......它的工作原理:)

Automatic conversions would only work for several specific types of containers, and that's it. 自动转换只适用于几种特定类型的容器,就是这样。 Just because conversion A works, and conversion B works, doesn't mean that conversion A will work too. 仅仅因为转换A有效,转换B有效,并不意味着转换A也会起作用。

You can pretty much forget about using the [] operator in all the cases where automatic conversion doesn't work. 在自动转换不起作用的所有情况下,你几乎可以忘记使用[]运算符。

A variant list of variant lists however might just work. 然而,变体列表的变体列表可能正常工作。 I haven't tested it myself but there is a slim hope. 我自己没有测试过,但是希望很小。 However, you will have to manually do the conversion before you pass that stuff to QML. 但是,在将这些内容传递给QML之前,您必须手动执行转换。

An approach that will most definitely work is to create accessor functions, like for example QString Class::get(int row, int col) or you can have separate accessors to select a row, and then pass that result to another function to select a column to give you the string. 绝对可行的方法是创建访问器函数,例如QString Class::get(int row, int col)或者您可以使用单独的访问器来选择行,然后将该结果传递给另一个函数以选择列给你字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM