我正在 Unix 中开发一个 Qt C++ 应用程序,我一直在尝试做一些类似于这张图片显示的事情:
如您所见,有一个文件和文件夹列表,用户可以选择其中的多个(如果选择了一个文件夹,则所有子项也会被选中)。我真的不在乎是否显示文件夹/文件图标。
我能够创建一个列表,QDir
其中存储了给定根路径的所有文件和文件夹路径。问题是我真的不知道要使用哪些小部件来设计选择面板。
顺便说一句,列表QDir
是一个向量,但它可以很容易地修改为其他任何东西。
谢谢!
您可以尝试为QFileSystemModel制作代理模型,使用 Qt::ItemIsUserCheckable 覆盖 flags(),覆盖 setData() 并将模型应用于 QTreeView。完整示例可以在https://github.com/em2er/filesysmodel找到。这段代码只是一个概念,我没有彻底测试过,但你可以从中获得一些想法。它看起来像在屏幕截图上: .
您还可以将其与合并代理模型结合使用,以在一个视图中显示多个起始路径。
您可能需要考虑 QTreeWidget,或者它是一个更高级的版本 - QTreeView 和适当的数据模型。
正如一些用户建议的那样,我最终使用QFileSystemModel
. 我将完整描述我是如何实现它的,以防其他人提出这个问题并需要明确的回应。
首先,aQFileSystemModel
是一个没有复选框的文件树,要添加它们,一个扩展的新类QFileSystemModel
必须覆盖至少 3 个方法。
class FileSelector : public QFileSystemModel
{
public:
FileSelector(const char *rootPath, QObject *parent = nullptr);
~FileSelector();
bool setData(const QModelIndex& index, const QVariant& value, int role);
Qt::ItemFlags flags(const QModelIndex& index) const;
QVariant data(const QModelIndex& index, int role) const;
private:
QObject *parent_;
/* checklist_ stores all the elements which have been marked as checked */
QSet<QPersistentModelIndex> checklist_;
};
创建模型时,必须设置一个标志,表明它应该有一个可复选框。这就是我们将使用该flags
功能的原因:
Qt::ItemFlags FileSelector::flags(const QModelIndex& index) const
{
return QFileSystemModel::flags(index) | Qt::ItemIsUserCheckable;
}
当在复选框中单击时,setData
将调用该方法,并使用被单击元素的索引(不是复选框本身,而是:
bool FileSelector::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (role == Qt::CheckStateRole && index.column() == 0) {
QModelIndexList list;
getAllChildren(index, list); // this function gets all children
// given the index and saves them into list (also saves index in the head)
if(value == Qt::Checked)
{
for(int i = 0; i < list.size(); i++)
{
checklist_.insert(list[i]);
// signals that a change has been made
emit dataChanged(list[i], list[i]);
}
}
else if(value == Qt::Unchecked)
{
for(int i = 0; i < list.size(); i++)
{
checklist_.remove(list[i]);
emit dataChanged(list[i], list[i]);
}
}
return true;
}
return QFileSystemModel::setData(index, value, role);
}
当dataChanged
发出信号或您打开树的新路径时,data
将调用该函数。在这里,您必须确保仅在第一列(文件名旁边)显示复选框,并检索复选框的状态,将其标记为选中/未选中。
QVariant FileSelector::data(const QModelIndex& index, int role) const
{
if (role == Qt::CheckStateRole && index.column() == 0) {
if(checklist_.contains(index)) return Qt::Checked;
else return Qt::Unchecked;
}
return QFileSystemModel::data(index, role);
}
我唯一无法完成的是获取所有孩子,因为必须打开文件夹才能检索孩子。所以一个封闭的文件夹在你打开它之前不会有任何子文件夹。
希望这可以帮助和我有同样问题的人!