簡體   English   中英

如何使用 C++ 在 QML ListModel 中插入 ListElement?

[英]How to insert ListElement in a QML ListModel using C++?

嗯,我正在學習使用 QML,我有一個疑問。 在我的示例中,我在 QML 有一個帶有 ListElements 的 ListModel,我有一個帶有矩形、PathView 等的 QML 主文件。

我也有一個 QWidget,而不是我的主窗口。 在這個 QWidget 中,我像組件一樣包含 QML UI。 行!

如何使用 C++ 處理 QML ListElements?
注意:當我說“處理”時,我想說例如包含一個元素。

下面是我的代碼的一些部分......

QML 包含我的 ListElement,稱為“Menu1”:

import QtQuick 1.0

ListModel {
    id: listMovieModel
    ListElement { name: "Image 1"; iconSource: "pics/image_1.jpg" }
    ListElement { name: "Image 2"; iconSource: "pics/image_2.jpg" }
    ListElement { name: "Image 3"; iconSource: "pics/image_3.jpg" }
    ListElement { name: "Image 4"; iconSource: "pics/image_4.jpg" }
    ListElement { name: "Image 5"; iconSource: "pics/image_5.jpg" }
    ListElement { name: "Image 6"; iconSource: "pics/image_6.jpg" }
}

我的主要 QML:

Rectangle {
    width: 500
    height: 600
    color: "transparent"

    PathView {
        id: view
        focus: true
        width: parent.width
        height: parent.height + y
        y: -150
        model: Menu1 {} //First QML showed
        delegate: Image {
            source: iconSource
            width: 64
            height: 90
            scale: PathView.isCurrentItem ? 3.5 * y / parent.height : 2.0 * y / parent.height
            z: y
            smooth: true
        }
        path: MyGeometricFigure { //This a another file, but is confidential
            width: view.width
            height: view.height
        }
        preferredHighlightBegin: 0
        preferredHighlightEnd: 0
        highlightRangeMode: PathView.StrictlyEnforceRange
        Keys.onLeftPressed: decrementCurrentIndex()
        Keys.onRightPressed: incrementCurrentIndex()
    }
}

當我將 QML 用作 QWidget 的組件時:

MainForm::MainForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MainForm)
{
    ui->setupUi(this);
    this->resize(1024, 576);

    QDeclarativeView *myQMLTest = new QDeclarativeView(QUrl::fromLocalFile("myMainQML.qml"));
    myQMLTest->setStyleSheet(QString("background: transparent; width: 600px"));

    this->ui->frameListVideoGallery->layout()->addWidget(myQMLTest);
    myQMLTest->setFocus();
    myQMLTest->installEventFilter(this);
}

我看到了一些關於此的文章,但我無法使用 C++ 更改我的 LisModel。 我在這里看到了http://doc.qt.nokia.com/4.7/qdeclarativemodels.html#c-data-models和這里在使用 PathView http://doc.qt.nokia.com/4.7/qdeclarativeexamples.html 的示例中

有人能幫我嗎?

謝謝!

好吧。 我認為你可以做這樣的事情:

在您的主 QML 文件中添加簡單的函數。

Rectangle {
    // ...

    function append(newElement) {
        view.model.append(newElement)
    }

    PathView {
        id: view

        // ...

        model: Menu1 {} //First QML showed

        // ...
    }
}

這個方法只會從 ListModel 調用相應的方法。 您可以在那里找到更多支持的方法。

那么你所需要的就是從 C++ 代碼中調用這個方法。 您可以通過以下方式執行此操作:

MainForm::MainForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MainForm)
{
    ui->setupUi(this);
    this->resize(1024, 576);

    QDeclarativeView *myQMLTest = new QDeclarativeView(QUrl::fromLocalFile    ("myMainQML.qml"));
    myQMLTest->setStyleSheet(QString("background: transparent; width: 600px"));

    QVariantMap newElement;  // QVariantMap will implicitly translates into JS-object
    newElement.insert("name",       "Image 13"         );
    newElement.insert("iconSource", "pics/image_13.jpg");

    QMetaObject::invokeMethod(
        myQMLTest->rootObject(),                          // for this object we will call method
        "append",                                         // actually, name of the method to call
        Q_ARG(QVariant, QVariant::fromValue(newElement))  // method parameter
    );

    this->ui->frameListVideoGallery->layout()->addWidget(myQMLTest);
    myQMLTest->setFocus();
    myQMLTest->installEventFilter(this);
}

你應該檢查這個以獲取更多信息。

您也可以選擇另一種方法:通過 qml 屬性(使用 QDeclarativeEngine 和 QDeclarativeContext)傳遞一些數據,然后在 JavaScript 代碼中處理這些數據和您的列表模型。

我想讓@GooRoo 的答案對 Qt 初學者更完整/有用。 如果您使用 Qt Creator,您將從使用 QmlApplicationViewer 的模板開始。 要應用 GooRoo 的答案,您必須執行以下操作(感謝http://www.lothlorien.com/kf6gpe/?p=309 ):

CPP:

Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QApplication> app(createApplication(argc, argv));
    QScopedPointer<QmlApplicationViewer> viewer(QmlApplicationViewer::create());

    viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer->setMainQmlFile(QLatin1String("qml/mydemo/main.qml"));
    viewer->showExpanded();

    QMetaObject::invokeMethod(
        (QObject *)viewer->rootObject()->findChild<QObject *>("myModel"), // QML item
        "test"                           // name of the method to call
                                         // without parameters
    );

    return app->exec();
}

QML:

PageStackWindow {
    id: mainApp
    ...

    ListModel {
        id: myModel
        objectName: myModel //THIS IS NEEDED BY findChild()
        ...
        function test() {
            console.log("TEST OK");
        }
    }

    Page {
        ...
    }
}

這是一個更完整的示例,它使用 C++ 在 QML TableView 中填充數據。 請原諒錯誤的變量名稱。 我只是為了測試目的而制作它。

我使用了QVariantList並用QVariantMap對象填充它。


在這里,多個數據在 QML 表的兩列中填充了 for 循環,即whatsession_name通過將它們放在QVariantMap ,然后將該QVariantMap插入QVariantList

小時

#ifndef HH_H
#define HH_H

#include <QVariant>

class AA : public QObject
{
    Q_OBJECT
    QVariantList m_gname;

public:
    Q_PROPERTY(QVariantList gname READ gname WRITE setGname NOTIFY gnameChanged)

    AA()
    {
        QVariantList q;

        for(int i = 0; i < 10; i++)
        {
            QVariantMap p;
            p.insert("what", "qq");
            p.insert("session_name", "aa");

            q.push_back(p);
        }
        setGname(q);
    }

    QVariantList gname() const
    {
        return m_gname;
    }

public slots:

    void setGname(QVariantList gname)
    {
        if (m_gname == gname)
            return;

        m_gname = gname;
        emit gnameChanged(m_gname);
    }

signals:
    void gnameChanged(QVariantList gname);
};


#endif // HH_H

在這里,我使用qmlRegisterType來注冊我在上面創建的類AA

主程序

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "HH.h"
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    qmlRegisterType<AA>("ZZZ", 1, 0, "AA");


    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

在 QML 中,我通過QtQuick.Controls 1.4創建了一個 TableView。 它有兩列,分別whatsession_name 我在這里創建了一個AA類的對象,並在其Component.onCompleted上創建了一個名為 <model_id> dot append ( <QVariantList_name> )

像這樣:

mymodel.append( gname )

主文件

import QtQuick 2.14
import QtQuick.Window 2.14
import QtQuick.Controls 1.4 as OldControls

import ZZZ 1.0

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

    AA
    {
        Component.onCompleted:
        {
            mymodel.append(gname)
        }
    }


    Rectangle
    {
        id: head
        anchors.centerIn: parent; height:  500; width:  500; border.color: "red"

            OldControls.TableView
            {
                anchors.fill: parent
                verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn
                horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOn

                OldControls.TableViewColumn
                {
                    role: "what"
                    title: "What"
                }
                OldControls.TableViewColumn
                {
                    role: "session_name"
                    title: "Session Name"
                }
                model: ListModel
                        {
                            id: mymodel
                        }
            }
     }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM