zoukankan      html  css  js  c++  java
  • QDir+QTreeWidget (QViewWidget) 展示文件系统树形目录

    Qt包含一组项目视图类,它们使用模型/视图体系结构来管理数据之间的关系以及数据呈现给用户的方式.

    这里我们使用QStandardItemModel/QDirModel和 QTreeView或者 QTreeWidge来完成文件系统目录的展示 。

    1.  QStandardItemModel,功能强大,可先了解下。

    QStandardItemModel q标准化模型类提供了一个用于存储定制数据的通用模型。 q标准化模型可以作为标准Qt数据类型的存储库。它是模型/视图类之一,也是Qt模型/视图框架的一部分。 q标准化模型提供了一种经典的基于项目的方法来处理模型。q标准化模型提供了q标准化模型中的项目。 q标准化模型实现了QAbstractItemModel接口,这意味着该模型可以用于提供支持该接口的任何视图中的数据(如QListView、QTableView和QTreeView,以及自定义的类型)。

    当您需要一个列表或树时,通常会创建一个空的q标准化模型,并使用appendRow()将项目添加到模型中,并使用item()来访问项目。如果您的模型代表一个表,那么您通常将表的维度传递给q标准化模型构造函数,并使用setItem()将条目放置到表中。您还可以使用setRowCount()和setColumnCount()来改变模型的维度。要插入项,请使用insertRow()或insertColumn(),并删除项目,使用removeRow()或removeColumn()。

    QStandardItemModel:基于项数据的标准数据模型,可以处理二维数据。维护一个二维的项数据数组,每个项是一个 QStandardltem 类的变量,用于存储项的数据、字体格式、对齐方式等。
    QTableView:二维数据表视图组件,有多个行和多个列,每个基本显示单元是一个单元格,通过 setModel() 函数设置一个 QStandardItemModel 类的数据模型之后,一个单元格显示 QStandardItemModel 数据模型中的一个项。
    QItemSelectionModel:一个用于跟踪视图组件的单元格选择状态的类,当在 QTableView 选择某个单元格,或多个单元格时,通过 QItemSelectionModel 可以获得选中的单元格的模型索引,为单元格的选择操作提供方便。

    这几个类之间的关系是:QTableView 是界面视图组件,其关联的数据模型是 QStandardItem Model,关联的项选择模型是 QItemSelectionModel,QStandardItemModel 的数据管理的基本单元是 QStandardItem。

    QStandardItemModel继承于QAbstractItemModel Class,用于存储标准模型的数据

    QTreeView继承于QAbstractItemView Class,用于显示树视图

    当需要一个列表或树时,通常会创建一个空的QStandardItemModel,并使用appendRow()将项添加到模型中,使用item()访问一个项。

    如果的模型表示一个表,那么通常会将表的维度传递给QStandardItemModel构造函数,并使用setItem()将项定位到表中。您还可以使用setRowCount()和setColumnCount()来更改模型的维度。要插入项目,使用insertRow()或insertColumn(),要删除项目,使用removeRow()或removeColumn()。

    如果模型表示一个树,可以对模型(Model)使用appendRow()增加QStandardItem,对QStandardItem使用appendRow()增加QStandardItem(子节点)。其中,每个item的行号row均以上一节点(父节点)为基准:

    2. QDirModel的使用
    Qt上可以使用QFileSystemModel和QDirModel都可以获得文件系统目录结构数据。这里以QDirModel为例进行说明。

    QDirModel类为本地文件系统提供了一个数据模型,显示我们采用QTreeView。

    按照系列教程(一)中对原理的讲解,只要具备model和view,那么就可以进行显示了。

    核心代码就三句话:

    model = new QDirModel;
    treeView = new QTreeView;
    treeView->setModel(model);
    创建一个model和view,再把model设置到view里面,view就可以显示数据了。是不是很简单。

    3. QDirModel + QTreeView + QlineEdit 显示绝对路径

        model  = new QDirModel;
        model->setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name);
        ui->treeView->header()->setStretchLastSection(true);
        ui->treeView->header()->setSortIndicator(0, Qt::AscendingOrder);
        ui->treeView->header()->setSortIndicatorShown(true);
        //treeView->header()->setClickable(true);
        QModelIndex index = model->index("C:Qt"/*QDir::currentPath()*/);
        ui-> treeView->expand(index);
        ui->treeView->scrollTo(index);
        ui->treeView->resizeColumnToContents(0);
        ui->treeView->setModel(model);
    =========================================================================
        if(!connect(ui->treeView , SIGNAL(doubleClicked(QModelIndex)) , this , SLOT(treeViewSelect(const QModelIndex)))){
            qDebug("--error:4 teeView singal
    ");
        }
    void MainWindow::treeViewSelect(const QModelIndex& index)
    {
          QString itemFullPath = model->filePath(index);
          QFileInfo fileInfo = model->fileInfo(index);
         //QStandardItem* item = QStandardItemModel::itemFromIndex(index);
          // QString itemFullPath = getItemFullPath(item);
           ui->lineEdit->setText(itemFullPath);
          qDebug()<<" parent : " <<itemFullPath;
    }
    
    

    ========================================================================

     4. QDirModel + QTreeWidget + QlineEdit 显示绝对路径 

    参考https://blog.csdn.net/houqd2012/article/details/21646121, 实现动态按需加载,能节省资源动态载入路径。

        QTreeWidgetItem *top = new QTreeWidgetItem(ui->treeWidget , QStringList(QString(tr("我的电脑"))));
        top->setCheckState(1,Qt::Checked);
        root.append(top);
        ui->treeWidget->insertTopLevelItems(0 , root);


        //! 绑定扫DirScan扫描完的信号,发送过来添加进树
        if(!connect(dirScan , SIGNAL(ItemScaned(QString,QFileInfo,int)) , this , SLOT(AddItem(QString,QFileInfo,int)))){
            qDebug("--error:1--
    ");
        }
    
        //! 绑定本地树控件的单击事件,经过处理后发送出去,参数为点击的path   //获得path绝对路径,转换后,发送信号量到扫描类
        if(!connect(ui->treeWidget , SIGNAL(itemClicked(QTreeWidgetItem*,int)) , this , SLOT(selectItem(QTreeWidgetItem* , int)))){
            qDebug("--error:2--
    ");
        }
    
        //! 绑定发送出去的事件,即发送给DirScan的事件
        if(!connect(this , SIGNAL(sendToDirScan(QString)) , dirScan , SLOT(Scan(QString)))){
            qDebug("--error:3--
    ");
        }
        
    void MainWindow::AddItem(const QString &strRootPath, const QFileInfo &ItemInfo , const int k)
    {
    
        if(ItemInfo.isDir()){
    
            if(ItemInfo.fileName() == QLatin1String(".") || ItemInfo.fileName() == QLatin1String("..")){
                return ;
            }
    
            QString fullPath = ItemInfo.absolutePath().replace("/" , "\") ;
    
    //        if(!QString::compare(strRootPath , rootPath)){
    //           return ;
    //        }
    
            qDebug("(fullPath: %s)
    " , fullPath.toLatin1().data());
    
            // 这个只是第一次走,剩下的肯定都是包含的,因为盘符是在最外面的
            if(!m_StoreDirItem.contains(fullPath)){
    
                QString showname = ( k ? ItemInfo.fileName() : ItemInfo.filePath() );
                qDebug("---not----contains----k = %d ---------showname = %s.
    " , k , showname.toLatin1().data());
                QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget->findItems(QString(tr("我的电脑")) , 0 , 0).at(0) , QStringList(showname));
    
                m_StoreDirItem.insert(fullPath , item);
    
            }else{
    
                qDebug("---------contains---------
    ");
                QTreeWidgetItem *item = m_StoreDirItem.value(fullPath);
                QTreeWidgetItem *item_1 = new QTreeWidgetItem(QStringList(ItemInfo.fileName()));
    
                int j ;
                for(j=0 ; j < item->childCount() ; j++){
                    if(!QString::compare(ItemInfo.fileName() , item->child(j)->text(0))){
                        break ;
                    }
                }
    
                if(j == item->childCount()){
                    item->addChild(item_1);
                    m_StoreDirItem.insert(ItemInfo.absoluteFilePath().replace("/","\") , item_1);
                }
            }
    
        }else if(ItemInfo.isFile()){
            qDebug(":::::::I am a file.
    ");
    
            QString fileFullPath = ItemInfo.filePath();
            QString filename = ItemInfo.fileName();
    
            QString file_path ;
    
            file_path = ItemInfo.absolutePath().replace("/","\");
    
            qDebug("::::::file_path = %s
    " , file_path.toLatin1().data());
    
            if(!m_StoreDirItem.contains(file_path)){
    
                qDebug("----not contains----
    ");
                QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget , QStringList(file_path));
                QTreeWidgetItem *item_1 = new QTreeWidgetItem(item , QStringList(filename));
                item->addChild(item_1);
    
                m_StoreDirItem.insert(file_path , item);
            }else{
    
                qDebug("---contains---
    ");
                QTreeWidgetItem *item = m_StoreDirItem.value(file_path);
                QTreeWidgetItem *item_1 = new QTreeWidgetItem(QStringList(filename));
                int j ;
                for( j = 0 ; j < item->childCount() ; j++){
                    if(!QString::compare(filename , item->child(j)->text(0))){
                        break ;
                    }
                }
    
                qDebug("---j = %d and childCount = %d 
    " , j , item->childCount());
                if(j == item->childCount()){
                    item->addChild(item_1);
                }
            }
        }
    
       return ;
    
    }

    5.  以下是一个QDir + QFileinfoList 遍历文件夹的实现,不知道QDirModel是否用类似方式来加载文件系统?

    QFileInfoList MainWindow::allFile(QTreeWidgetItem *root,QString path)
    {
        /*添加path路径文件*/
        qDebug("first 
    ");
            QDir dir(path);          //遍历各级子目录
            QDir dir_file(path);    //遍历子目录中所有文件
            dir_file.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);        //获取当前所有文件
            dir_file.setSorting(QDir::Size | QDir::Reversed);
            QFileInfoList list_file = dir_file.entryInfoList();
            for (int i = 0; i < list_file.size(); ++i) {       //将当前目录中所有文件添加到treewidget中
                QFileInfo fileInfo = list_file.at(i);
                QString name2=fileInfo.fileName();
                QTreeWidgetItem* child = new QTreeWidgetItem(QStringList()<<name2);
                child->setIcon(0, QIcon(":/file/image/link.ico"));
                child->setCheckState(1, Qt::Checked);
                root->addChild(child);
            }
        qDebug("second 
    ");
    
            QFileInfoList file_list=dir.entryInfoList(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
            QFileInfoList folder_list = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);   //获取当前所有目录
    
            for(int i = 0; i != folder_list.size(); i++)         //自动递归添加各目录到上一级目录
            {
    
                     QString namepath = folder_list.at(i).absoluteFilePath();    //获取路径
                     QFileInfo folderinfo= folder_list.at(i);
                     QString name=folderinfo.fileName();      //获取目录名
                     QTreeWidgetItem* childroot = new QTreeWidgetItem(QStringList()<<name);
                     childroot->setIcon(0, QIcon(":/file/image/link.ico"));
                     childroot->setCheckState(1, Qt::Checked);
                     root->addChild(childroot);              //将当前目录添加成path的子项
                     QFileInfoList child_file_list = allFile(childroot,namepath);          //进行递归
                     file_list.append(child_file_list);
                     file_list.append(name);
             }
            return file_list;
    
    }

    5.总结

    Qt的模型/视图功能很灵活,需要经常使用才能掌握其要领,这个练习只是第一步,需要更多的实战来掌握其结构和使用方式。

  • 相关阅读:
    ReactNative之从HelloWorld中看环境搭建、组件封装、Props及State
    iOS开发之虾米音乐频道选择切换效果分析与实现
    Cocoa包管理器之Carthage详解及CocoaPods中心化+Carthage的二进制化
    Cocoa包管理器之CocoaPods详解
    Git知识总览(六) Git分支中的远程操作实践
    Git知识总览(五) Git中的merge、rebase、cherry-pick以及交互式rebase
    Git知识总览(四) git分支管理之rebase 以及 cherry-pick相关操作
    Git知识总览(三) 分支的创建、删除、切换、合并以及冲突解决
    Git知识总览(二) git常用命令概览
    Git知识总览(一) 从 git clone 和 git status 谈起
  • 原文地址:https://www.cnblogs.com/7star/p/13719225.html
Copyright © 2011-2022 走看看