QT学习教程11-QTreeView显示系统目录并实现复选框

目录

  • 完成的功能秃
  • 使用QTreeView显示系统目录

完成的功能秃

QT学习教程11-QTreeView显示系统目录并实现复选框_第1张图片

使用QTreeView显示系统目录

其实这里显示目录的难度不大,也就只有几行代码就实现了,较难的在显示三态,这里只实现了checkbox的checked与unchecked的功能。
贴一下代码:
mytreemodel,h:

#ifndef MYTREEMODEL_H
#define MYTREEMODEL_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
class MyTreeModel : public QDirModel
{
    Q_OBJECT
public:
    explicit MyTreeModel(QWidget *parent = nullptr);

    ~MyTreeModel();
    QSet<QPersistentModelIndex> checkedIndexes;
    Qt::ItemFlags flags(const QModelIndex &index) const;
    QVariant data(const QModelIndex &index, int role) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role);
private:
    bool recursiveCheck(const QModelIndex &index, const QVariant &value);

signals:

public slots:
};

#endif // MYTREEMODEL_H

mytreeview,h:

#ifndef MYLISTVIEW_H
#define MYLISTVIEW_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
class MyTreeView : public QWidget
{
        Q_OBJECT
public:
        MyTreeView();
        QSet<QPersistentModelIndex> checkedIndexes;
        Qt::ItemFlags flags(const QModelIndex &index) const;
        QVariant data(const QModelIndex &index, int role) const;
        bool setData(const QModelIndex &index, const QVariant &value, int role);
private:
        bool recursiveCheck(const QModelIndex &index, const QVariant &value);

public:
        QDirModel *model;
        QTreeView *treeView;

public slots:
        void mkdir();
        void rm();
        void slotCustomContextMenu(const QPoint &point);
        //void ShowContextMenu(const QPoint& pos);
protected:
      //  QMenu menu;

};

#endif // MYLISTVIEW_H

main.cpp:

#include "mytreeview.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyTreeView w;
    w.show();

    return a.exec();
}

mytreemodel.cpp:

#include "mytreemodel.h"

MyTreeModel::MyTreeModel(QWidget *parent) : QDirModel(parent)
{

}
MyTreeModel::~MyTreeModel()
{
}
/*flags( )中返回 ItemIsUserCheckable。*/
Qt::ItemFlags MyTreeModel::flags(const QModelIndex &index) const
{
    return QDirModel::flags(index) | Qt::ItemIsUserCheckable;
}
/*data( )中判断给定的项是否在checkedIndexes中,有的话就返回Qt::Checked,没有 就返回Qt::Unchecked。*/
QVariant MyTreeModel::data(const QModelIndex &index, int role) const
{
    if(role == Qt::CheckStateRole)
    {
         qDebug()<<"The checkbox is unchecked"<<checkedIndexes.contains(index);
//        if(checkedIndexes.contains(index)==Qt::Checked){
//            qDebug()<<"The checkbox is checked"<
//            return Qt::Checked;
//        }
//        else if(checkedIndexes.contains(index)==Qt::Unchecked){
//            qDebug()<<"The checkbox is unchecked"<
//            return Qt::Unchecked;
//        }
//        else if(checkedIndexes.contains(index)==Qt::PartiallyChecked) {
//            qDebug()<<"The checkbox is part checked"<
//            return Qt::PartiallyChecked;
//        }
        return checkedIndexes.contains(index) ? Qt::Checked : Qt::Unchecked;
        //这个返回值就只有两种情况,不是真就是假
    }
    else
    {
        return QDirModel::data(index, role);
    }
}
/*setData( )则把值为Qt::Checked的给定项,以及给定项的所有子孙节点,全都添加到checkedIndexes里。*/
bool MyTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if(role == Qt::CheckStateRole)
    {
        if(value == Qt::Checked)
        {
//            if(recursiveCheck(index, value)==false){

//            }
            checkedIndexes.insert(index);//把给点项的子孙节点加入checkedIndexes
            if(hasChildren(index) == true)//如果这个节点有子孙节点,递归把所有节点都加入这个index.
            {
                recursiveCheck(index, value);
            }
        }
        else if(value == Qt::Unchecked)
        {
            checkedIndexes.remove(index);
            if(hasChildren(index) == true)
            {
                recursiveCheck(index, value);
            }
        }
        else{
            qDebug()<<"this is exec";
        }
        emit dataChanged(index, index);
        return true;
    }
    return QDirModel::setData(index, value, role);
}
/*recursiveCheck( )用于递规添加子节点。*/
bool MyTreeModel::recursiveCheck(const QModelIndex &index, const QVariant &value)
{
    if(hasChildren(index))
    {
        int i;
        int childrenCount = rowCount(index);
        QModelIndex child;
        for(i=0; i<childrenCount; i++)
        {
            child = QDirModel::index(i, 0, index);
            setData(child, value, Qt::CheckStateRole);
        }
         return QDirModel::setData(child, value, Qt::CheckStateRole);
    }

}

mytreeview.cpp:

#include "mytreeview.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
MyTreeView::MyTreeView()
{
        model = new MyTreeModel();
        model->setReadOnly(false);//就是说我们可以对其进行修改
        model->setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name);//文件夹优先(QDir::DirsFirst),忽略大小写(QDir::IgnoreCase),而且是根据名字排序(QDir::Name)。
//QDirModel。这个 model 允许我们在 view 中显示操作系统的目录结构。
        treeView = new QTreeView;
        treeView->setModel(model);//把 model 设置为刚刚的 QDirModel 实例
        treeView->header()->setStretchLastSection(true);//当 QTreeView 的宽度大于所有列宽之和时,最后一列的宽度自动扩展以充满最后的边界;否则就让最后一列的宽度保持原始大小。
        treeView->header()->setSortIndicator(0, Qt::AscendingOrder);//setSortIndicator()函数是设置哪一列进行排序。
        treeView->header()->setSortIndicatorShown(true);//setSortIndicatorShown()函数设置显示列头上面的排序小箭头。setClickable(true)则允许鼠标点击列头。
        //treeView->header()->setClickable(true);
        treeView->setEditTriggers(QTreeView::NoEditTriggers);			//单元格不能编辑
        treeView->setSelectionBehavior(QTreeView::SelectRows);			//一次选中整行
        treeView->setSelectionMode(QTreeView::SingleSelection);        //单选,配合上面的整行就是一次选单行
        treeView->setAlternatingRowColors(true);                       //每间隔一行颜色不一样,当有qss时该属性无效
        treeView->setFocusPolicy(Qt::NoFocus);

        QModelIndex index = model->index(QDir::currentPath());//通过 QDir::currentPath()获取当前 exe 文件运行时路径,并把这个路径当成程序启动时显示的路径。
        treeView->expand(index);
        treeView->scrollTo(index);//scrollTo()函数是把视图的视口滚动到这个路径的位置;
        treeView->resizeColumnToContents(0);//resizeColumnToContents()是要求把列头适应内容的宽度,也就是不产生...符号。
//        QHBoxLayout *btnLayout = new QHBoxLayout;
//        QPushButton *createBtn = new QPushButton(tr("Create Directory..."));
//        QPushButton *delBtn = new QPushButton(tr("Remove"));
//        btnLayout->addWidget(createBtn);
//        btnLayout->addWidget(delBtn);
        QVBoxLayout *mainLayout = new QVBoxLayout(this);//垂直布局
        treeView->setContextMenuPolicy(Qt::CustomContextMenu);
        connect(treeView, SIGNAL(customContextMenuRequested(const QPoint& )), this, SLOT(slotCustomContextMenu(const QPoint&)));
        mainLayout->addWidget(treeView);
       // mainLayout->addLayout(btnLayout);
        this->setLayout(mainLayout);
        //connect(createBtn, SIGNAL(clicked()), this, SLOT(mkdir()));
        //connect(delBtn, SIGNAL(clicked()), this, SLOT(rm()));
}
void MyTreeView::slotCustomContextMenu(const QPoint &point) //槽函数定义
{
        QMenu *menu = new QMenu(this);
        menu->addAction("delete",this,SLOT(rm()));     //设置菜单项,并连接槽函数
        menu->addAction("add",this,SLOT(mkdir()));
        menu->exec(this->mapToGlobal(point));
}
void MyTreeView::mkdir()
{
        QModelIndex index = treeView->currentIndex();
        if (!index.isValid()) {
                return;
        }
        QString dirName = QInputDialog::getText(this,
              tr("Create Directory"),
              tr("Directory name"));
        if (!dirName.isEmpty()) {
                if (!model->mkdir(index, dirName).isValid()) {
                        QMessageBox::information(this,
                    tr("Create Directory"),
                    tr("Failed to create the directory"));
                }
        }
}
void MyTreeView::rm()
{
        QModelIndex index = treeView->currentIndex();
        int row = index.row();
        if (!index.isValid()) {
                return;
        }
        bool ok;
        if (model->fileInfo(index).isDir()) {//判断是一个文件夹吗,无法删除嵌套其他文件夹的文件夹
                ok = model->rmdir(index);
        } else {
                ok = model->remove(index);//判断是一个文件吗
        }
        if (!ok) {
                QMessageBox::information(this,
             tr("Remove"),
             tr("Failed to remove %1").arg(model->fileName(index)));
        }
}

该有的注释我也都基本写在代码里了,这个难度不是特别大,后面会接下去实现三态,以及文件从一个QTreeView复制到另一个QTreeView之中。

你可能感兴趣的:(QT学习教程)