3

我正在 Unix 中开发一个 Qt C++ 应用程序,我一直在尝试做一些类似于这张图片显示的事情:

在此处输入图像描述

如您所见,有一个文件和文件夹列表,用户可以选择其中的多个(如果选择了一个文件夹,则所有子项也会被选中)。我真的不在乎是否显示文件夹/文件图标。

我能够创建一个列表,QDir其中存储了给定根路径的所有文件和文件夹路径。问题是我真的不知道要使用哪些小部件来设计选择面板。

顺便说一句,列表QDir是一个向量,但它可以很容易地修改为其他任何东西。

谢谢!

4

3 回答 3

2

您可以尝试为QFileSystemModel制作代理模型,使用 Qt::ItemIsUserCheckable 覆盖 flags(),覆盖 setData() 并将模型应用于 QTreeView。完整示例可以在https://github.com/em2er/filesysmodel找到。这段代码只是一个概念,我没有彻底测试过,但你可以从中获得一些想法。它看起来像在屏幕截图上: 它看起来像在屏幕截图上.

您还可以将其与合并代理模型结合使用,以在一个视图中显示多个起始路径。

于 2017-03-13T22:32:03.450 回答
1

您可能需要考虑 QTreeWidget,或者它是一个更高级的版本 - QTreeView 和适当的数据模型。

于 2017-03-13T20:33:05.673 回答
1

正如一些用户建议的那样,我最终使用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);
}

我唯一无法完成的是获取所有孩子,因为必须打开文件夹才能检索孩子。所以一个封闭的文件夹在你打开它之前不会有任何子文件夹。

希望这可以帮助和我有同样问题的人!

于 2017-03-14T18:05:23.467 回答