首页 > 解决方案 > 在运行时将带有类实例的列表从 c++ 导入到 qml 的建议

问题描述

我有一个 QList,其中每个元素都是 C++ 类的一个实例。这些实例包含信息,并基于我想在 QML 中创建和移动矩形。包含的信息是 x 位置(除其他外),我想为 QList 中的每个元素创建/移动一个矩形。QList 在运行时定期更新,这意味着可以添加、删除某些元素或编辑 x 位置。

我编写了一个小示例来了解如何完成 c++ 和 QML 之间的桥梁,但我认为我的代码只能作为初始化工作一次,如果我在运行时更新 QList 则不会。我是否在正确的轨道上,如果没有,我必须改变什么?是否有必要使用 QAbstractListModel 就像Timmmmm在这个问题的答案中所建议的那样?

这是我的代码:
class.h:

#ifndef CLASS_H
#define CLASS_H

#include <QQuickItem>

class RectangelClass : public QObject
{
private:
    Q_OBJECT
    Q_PROPERTY(int xPos READ xPos WRITE setXPos NOTIFY xPosChanged)
    int m_xPos;

public:
    RectangelClass () {}
    int xPos() const { return m_xPos; }

public slots:
    void setXPos(int arg)
    {
        if (m_xPos == arg)
            return;

        m_xPos = arg;
        emit xPosChanged(arg);
    }

signals:
    void xPosChanged(int arg);
};

class RectangelClassManager : public QObject
{
private:
    Q_OBJECT
    Q_PROPERTY(QList <QObject*> rectangelClassList READ rectangelClassList WRITE setRectangelClassList NOTIFY rectangelClassListChanged)
    QList <QObject*> m_rectangelClassList;

public:
    RectangelClassManager ()
    {
        QList <QObject*> localObjList;
        for (int i = 0; i < 5; i++)
        {
            RectangelClass *localObj = new RectangelClass();
            localObj->setXPos (i*100);
            localObjList.push_back(localObj);
        }

        setRectangelClassList (localObjList);

    }

    QList <QObject*> rectangelClassList () const { return m_rectangelClassList; }

public slots:
    void setRectangelClassList (QList <QObject*> arg)
    {
        if (m_rectangelClassList == arg)
            return;

        m_rectangelClassList = arg;
        emit rectangelClassListChanged(arg);
    }

signals:
    void rectangelClassListChanged (QList <QObject*> arg);
};

#endif // CLASS_H

主.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "class.h"
#include <iostream>

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

    qmlRegisterType<RectangelClass>("cppclasses", 1, 0, "RectangelClass");
    qmlRegisterType<RectangelClassManager>("cppclasses", 1, 0, "RectangelClassManager");

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

    return app.exec();
}

main.qml:

import QtQuick 2.4
import QtQuick.Window 2.2
import cppclasses 1.0


Window {

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

    RectangelClassManager{
        id: rectangelClassManager
    }

    Rectangle{
        id: rect0
        x: rectangelClassManager.rectangelClassList[0].xPos
        y: 100
        width: 80
        height: 80
        color:"yellow"
        Text {
            id: textid0
            anchors.centerIn: parent
            text: "X-Position: " + rectangelClassManager.rectangelClassList[0].xPos
        }
    }

    Rectangle{
        id: rect1
        x: rectangelClassManager.rectangelClassList[1].xPos
        y: 100
        width: 80
        height: 80
        color:"yellow"
        Text {
            id: textid1
            anchors.centerIn: parent
            text: "X-Position: " + rectangelClassManager.rectangelClassList[1].xPos
        }
    }

    Rectangle{
        id: rect2
        x: rectangelClassManager.rectangelClassList[2].xPos
        y: 100
        width: 80
        height: 80
        color:"yellow"
        Text {
            id: textid2
            anchors.centerIn: parent
            text: "X-Position: " + rectangelClassManager.rectangelClassList[2].xPos
        }
    }

    Rectangle{
        id: rect3
        x: rectangelClassManager.rectangelClassList[3].xPos
        y: 100
        width: 80
        height: 80
        color:"yellow"
        Text {
            id: textid3
            anchors.centerIn: parent
            text: "X-Position: " + rectangelClassManager.rectangelClassList[3].xPos
        }
    }

    Rectangle{
        id: rect4
        x: rectangelClassManager.rectangelClassList[4].xPos
        y: 100
        width: 80
        height: 80
        color:"yellow"
        Text {
            id: textid4
            anchors.centerIn: parent
            text: "X-Position: " + rectangelClassManager.rectangelClassList[4].xPos
        }
    }
}

编辑以使我的问题更清楚:
是否可以在 C++ 中在运行时更新 QList,是否会在 QML 中更新,如果没有,我该如何实现。

标签: c++qtqml

解决方案


是的,QList可以通过发出rectangelClassListChanged()信号在运行时更新属性。但是,这可能非常低效,因为整个列表都被重新解析了。因此,根据您QList更改的频率,您最好将其更改为QAbstractListModel.

此外,您可以将代码更改为使用 a Repeater,这会伤害我的程序员的眼睛 ;-) 这实际上可能是不更新运行时的原因。

import QtQuick 2.4
import QtQuick.Window 2.2
import cppclasses 1.0


Window {

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

    RectangelClassManager{
        id: rectangelClassManager
    }

    Repeater {
        model: rectangelClassManager.rectangelClassList

        delegate: Rectangle {
            x: modelData.xPos
            y: 100
            width: 80
            height: 80
            color:"yellow"
            Text {
                id: textid0
                anchors.centerIn: parent
                text: "X-Position: " + modelData.xPos
            }
        }
    }
}

推荐阅读