You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QVector自定义类作为Qt QML ListView模型无内容显示问题

问题:自定义类的QVector无法作为QML ListView模型显示内容

我尝试将自定义类的QVector绑定为QML ListView的模型,但屏幕无任何内容显示。初始化后List不为空,即使将属性改为非const并触发ListChanged信号,文本仍未显示。在ListView的Component.onCompleted中打印_Controller._List,输出为qml: QVariant(QList<Subject>, )。

以下是我的代码:

自定义Subject类

class Subject : public QObject
{
    Q_OBJECT
public:
    int First;
    int Second;

    explicit Subject(int fFirst = 0, int fSecond = 0, QObject *parent = nullptr)
    {
        this->First = fFirst;
        this->Second = fSecond;
        emit FirstChanged();
        emit SecondChanged();
    }
    Subject::Subject(const Subject &Copy)
    {
    this->First = Copy.First;
    this->Second = Copy.Second;
    emit FirstChanged();
    emit SecondChanged();
    }
    void Subject::operator=(const Subject &Right)
    {
    this->First = Right.First;
    this->Second = Right.Second;
    }
    
private:
    Q_PROPERTY(int _First READ getFirst WRITE setFirst  NOTIFY FirstChanged FINAL)
    Q_PROPERTY(int _Second READ getSecond WRITE setSecond NOTIFY SecondChanged FINAL)
};

Controller类

class Controller : public QObject
{
    Q_OBJECT
public:
    explicit Controller(QObject *parent = nullptr)
    {
        this->List.push_back(Subject(1, 0));
        this->List.push_back(Subject(2, 0));
    }
    QVector<Subject> List;
    QVector<Subject> getList() const;
    void setList(const QVector<Subject> &newList);

    Q_INVOKABLE void printAll();
private:
    Q_PROPERTY(QVector<Subject> _List READ getList CONSTANT)
};

QML代码

Controller
{
    id: _Controller
    Component.onCompleted:
    {
        _Controller.printAll()
    }
}
ListView
{
    anchors.fill: parent
    model: _Controller._List
    Component.onCompleted:
    {
        for (let i = 0; i < 2; i++)
        {
            console.log(_Controller._List)
        }
    }
    delegate: Text {
        id: _delegated
        text: qsTr(modelData._First)
        font.bold: true
        color: "black"
        font.pointSize: 24
    }
}

解决方案

你的代码存在几个关键问题,导致QML无法正确识别和遍历QVector中的数据:

1. 未注册自定义类型到QML

QML无法直接识别未注册的C++自定义类,需在main函数中通过qmlRegisterType注册类型:

#include <QQmlApplicationEngine>
#include "subject.h"
#include "controller.h"

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

    qmlRegisterType<Subject>("com.yourcompany.models", 1, 0, "Subject");
    qmlRegisterType<Controller>("com.yourcompany.controllers", 1, 0, "Controller");

    QQmlApplicationEngine engine;
    const QUrl url(u"qrc:/main.qml"_qs);
    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文件开头导入注册的模块:

import com.yourcompany.models 1.0
import com.yourcompany.controllers 1.0

2. QVector存储QObject派生类的方式错误

QObject派生类不能直接以值类型存储在QVector中(会引发对象所有权和拷贝冲突),必须存储指针类型QVector<Subject*>,且要删除Subject类中的拷贝构造函数和赋值运算符(QObject默认禁用拷贝)。

修改Controller类:

class Controller : public QObject
{
    Q_OBJECT
public:
    explicit Controller(QObject *parent = nullptr)
    {
        // 指定父对象避免内存泄漏
        List.push_back(new Subject(1, 0, this));
        List.push_back(new Subject(2, 0, this));
    }
    QVector<Subject*> List;
    QVector<Subject*> getList() const { return List; }
    void setList(const QVector<Subject*> &newList);

    Q_INVOKABLE void printAll();
private:
    Q_PROPERTY(QVector<Subject*> _List READ getList CONSTANT)
};

3. Q_PROPERTY的定义错误

Subject类中的Q_PROPERTY权限错误,且未实现对应的读写方法,需修正为:

class Subject : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int first READ first WRITE setFirst NOTIFY firstChanged FINAL)
    Q_PROPERTY(int second READ second WRITE setSecond NOTIFY secondChanged FINAL)
public:
    explicit Subject(int fFirst = 0, int fSecond = 0, QObject *parent = nullptr)
        : QObject(parent), m_first(fFirst), m_second(fSecond)
    {
    }

    int first() const { return m_first; }
    void setFirst(int first) {
        if (m_first != first) {
            m_first = first;
            emit firstChanged();
        }
    }

    int second() const { return m_second; }
    void setSecond(int second) {
        if (m_second != second) {
            m_second = second;
            emit secondChanged();
        }
    }

signals:
    void firstChanged();
    void secondChanged();

private:
    int m_first;
    int m_second;
};

4. QML中模型数据的访问修正

修改QML的delegate,使用正确的属性名访问:

delegate: Text {
    text: qsTr(modelData.first.toString())
    font.bold: true
    color: "black"
    font.pointSize: 24
}

可选优化:使用QAbstractListModel

如果需要支持模型数据的动态增删改,推荐继承QAbstractListModel实现自定义模型,这更符合Qt Model-View架构,能自动通知QML数据变化。


内容的提问来源于stack exchange,提问作者VoiceShifter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:00:58