QAbstractListModel::Data()未被调用,QML无法显示C++模型数据
问题排查与解决
你的QML看不到数据的核心原因是两个关键的实现错误,导致QML无法正确和C++模型交互:
1. 角色名方法拼写错误,QML无法识别数据角色
你在UserListModel里写的是rolesNames()(多了一个s),但Qt的QAbstractItemModel要求的虚函数是**roleNames()**(少一个s)!这个拼写错误直接导致QML无法获取你定义的macRole对应的"mac"角色名,自然不会触发data()方法去拿数据。
修复方法:把方法名改成正确的roleNames(),并且加上override关键字确保正确重写父类方法:
QHash<int, QByteArray> roleNames() const override { QHash<int, QByteArray> roles; roles[macRole] = "mac"; return roles; }
2. index()和parent()方法实现完全错误
QAbstractListModel是一维列表模型,这两个方法的实现规则很明确:
parent():列表里的每一项都没有父节点,所以必须返回空的QModelIndexindex():需要调用createIndex()生成对应行的有效索引,而不是直接返回入参
你原来的实现会让QML无法正确遍历模型结构,根本找不到要显示的列表项,所以data()和roleNames()都不会被调用。
修复这两个方法:
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override { // 列表模型只有一列,且父节点必须为空 if (!hasIndex(row, column, parent)) return QModelIndex(); return createIndex(row, column, nullptr); } QModelIndex parent(const QModelIndex &index) const override { // 列表项无父节点,返回空索引 Q_UNUSED(index); return QModelIndex(); }
额外优化建议
- 你的
User类如果要支持属性通知(比如后续修改mac地址自动更新UI),需要继承QObject并添加Q_PROPERTY,同时setMacAddr的参数建议用const QString&避免不必要的拷贝:class User : public QObject { Q_OBJECT Q_PROPERTY(QString macAddr READ macAddr WRITE setMacAddr NOTIFY macAddrChanged) private: QString m_macAddr; public: explicit User(QObject *parent = nullptr) : QObject(parent) {} User(const QString &mac, QObject *parent = nullptr) : QObject(parent), m_macAddr(mac) {} QString macAddr() const { return m_macAddr; } void setMacAddr(const QString &mac) { if (mac == m_macAddr) return; m_macAddr = mac; emit macAddrChanged(); } signals: void macAddrChanged(); }; - 你自定义的
getIndex()方法其实是多余的,QAbstractListModel原生的index()方法修复后就能正常生成索引,不需要额外定义。
为什么main函数里调用data()能拿到数据?
因为你在main里是通过getIndex()直接调用createIndex()生成了有效索引,绕开了你错误实现的index()方法,所以能正常获取数据,但QML是通过模型的标准接口去访问的,自然就失败了。
修复完上面两个核心问题后,你的QML ListView应该就能正常显示每个项的mac地址了。
内容的提问来源于stack exchange,提问作者Samir N Ahmad
相关产品推荐
相关产品推荐

