继承QFileSystemModel后为何无法用Qt::CheckStateRole存复选框状态?
Qt::CheckStateRole的原因及解决方法 我先帮你梳理下几个核心问题——从QFileSystemModel派生做自定义勾选逻辑,踩这些坑太正常了:
没有重写
data()函数返回勾选状态QFileSystemModel本身并没有实现Qt::CheckStateRole的返回逻辑,默认情况下这个角色是没有有效值的。你需要在派生类里维护一个存储结构(比如QMap<QUrl, Qt::CheckState>),用来记录每个文件/文件夹的勾选状态,然后重写data()函数:QVariant MyFileSystemModel::data(const QModelIndex &index, int role) const override { if (role == Qt::CheckStateRole) { QUrl itemUrl = this->fileUrl(index); return m_checkStates.value(itemUrl, Qt::Unchecked); } return QFileSystemModel::data(index, role); }没重写
setData()来更新状态
当用户点击复选框时,委托会调用setData()来更新状态,但原模型不会处理Qt::CheckStateRole的更新请求。你需要重写这个函数,把新的勾选状态存入你的存储结构,还要记得发出dataChanged信号通知视图更新:bool MyFileSystemModel::setData(const QModelIndex &index, const QVariant &value, int role) override { if (role == Qt::CheckStateRole) { QUrl itemUrl = this->fileUrl(index); m_checkStates[itemUrl] = static_cast<Qt::CheckState>(value.toInt()); emit dataChanged(index, index, {Qt::CheckStateRole}); return true; } return QFileSystemModel::setData(index, value, role); }忘记修改项的flags以支持勾选
视图需要明确知道项是可以被用户勾选的,所以得重写flags()函数,给项加上Qt::ItemIsUserCheckable标记:Qt::ItemFlags MyFileSystemModel::flags(const QModelIndex &index) const override { return QFileSystemModel::flags(index) | Qt::ItemIsUserCheckable; }混淆了内置角色和自定义角色的作用
你提到添加了UrlStringRole到roleNames()里,但Qt::CheckStateRole是Qt内置的标准角色,不需要在roleNames()中注册——roleNames()主要是给QML环境做角色名映射用的,在Widget的TreeView里直接用角色值就可以,注册它并不会帮助你实现勾选状态的存储。
如果需要处理文件夹的递归勾选(比如勾选父文件夹自动勾选子项),你还要额外在setData里遍历子项更新状态,不过这属于扩展功能,先把基础的勾选状态保存逻辑跑通再说。
内容的提问来源于stack exchange,提问作者numberCruncher

