Qt 文件树的实现

Qt 文件树的实现(QTreeWidget,QTreeWidgetItem)

使用Qt框架创建文件树主要是使用了Qt仲的QTreeWidget控件和QTreeWidgetItem控件。
其最主要的功能包括文件树的构建、文件的折叠与展开、对文件的新建、删除、重命名等操作,

  • 文件树的构建使用的是使用深度优先遍历的方式扫描所选择的文件夹,并将所扫描的符合要求的文件创建QTreeWidgetItem对象并规定所属关系。
  • 文件的折叠与展开这个功能本身并不需要我们自己去实现,QTreeWidget控件和QTreeWidgetItem控件的结合已经给我们提供了这样的功能,我们只需要在创建文件树的时候规定Item的所属关系即可。
  • 对文件的新建、删除、重命名。主要同操作Item右击菜单栏来实现。

效果如图所示

具体实现见代码

// 创建文件时 弹出的窗体
class NewBulidFile : public QDialog{
    Q_OBJECT
public:
    NewBulidFile(QWidget *parent=0);
    QLineEdit *fileNameEdit;
    QComboBox *fileNameTypeBox;
    QPushButton *okButton;
    QPushButton *cancalButton;
};
// 创建文件夹时弹出的窗体
class NewBuildfolder : public QDialog
{
    Q_OBJECT
public:
    NewBuildfolder(QWidget *parent=0);
    QLineEdit *fileNameEdit;
    QPushButton *okButton;
    QPushButton *cancalButton;
};

// 显示文件树的窗体
class TreeMenu : public QTreeWidget{
    Q_OBJECT
public:
    TreeMenu(QWidget *parent = 0);
    void CreateTopItem(QString path);
    void FindFile(QDir *path,QTreeWidgetItem *parent);
    void buttonCollapseItem();
private:
    QTreeWidgetItem *root; //树的根
    QMenu *dirMenu;  //文件夹菜单栏
    QMenu *fileMenu;  //文件菜单栏
    QTreeWidgetItem *nowItem; //当前光标所在Item
    int nowCol; //当前所在列
    NewBulidFile *newFileWidget;
    NewBuildfolder *newDirWidget;
signals:
    void showTextSignal(QString path,QString name,QTreeWidgetItem *item);
    void collapseItemSignal(const QTreeWidgetItem *item);
    void renameSignal();
private slots:
    void DoubleClickpath(QTreeWidgetItem *item, int column);
    void itemPressedSlot(QTreeWidgetItem * pressedItem, int column);
    void tempActionInformation(QAction *act);
    void bulidNewFileSlot(bool flag);
    void closeBuildFileSlot(bool flag);
    void buildNewDirSlot(bool flag);
    void cancelDirSlot(bool flag);
};

NewBulidFile::NewBulidFile(QWidget *parent):QDialog(parent){
    QLabel *fileNameLabel = new QLabel("文件名");
    QLabel *fileNameTypeLabel = new QLabel("文件类型");
    fileNameEdit = new QLineEdit();
    fileNameTypeBox = new QComboBox();
    fileNameTypeBox->addItem(".txt"); //这里可以多加几个Item,方法类似,用于新建文件时指定文件的类型
    okButton = new QPushButton("确定");
    cancalButton = new QPushButton("取消");

    QHBoxLayout *Hlayout1 = new QHBoxLayout();
    Hlayout1->addWidget(fileNameLabel);
    Hlayout1->addWidget(fileNameEdit);
    QHBoxLayout *Hlayout2 = new QHBoxLayout();
    Hlayout2->addWidget(fileNameTypeLabel);
    Hlayout2->addWidget(fileNameTypeBox);
    QHBoxLayout *Hlayout3 = new QHBoxLayout();
    Hlayout3->addWidget(okButton);
    Hlayout3->addWidget(cancalButton);
    QVBoxLayout *MainVlayout = new QVBoxLayout(this); //布局使用嵌套布局
    MainVlayout->addLayout(Hlayout1);
    MainVlayout->addLayout(Hlayout2);
    MainVlayout->addLayout(Hlayout3);
    this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
}

NewBuildfolder::NewBuildfolder(QWidget *parent):QDialog(parent){
    QLabel *fileNameLabel = new QLabel("新建文件夹");
    fileNameEdit = new QLineEdit();
    okButton = new QPushButton("确定");
    cancalButton = new QPushButton("取消");
    QHBoxLayout *Hlayout1 = new QHBoxLayout();
    Hlayout1->addWidget(fileNameLabel);
    Hlayout1->addWidget(fileNameEdit);
    QHBoxLayout *Hlayout2 = new QHBoxLayout();
    Hlayout2->addWidget(okButton);
    Hlayout2->addWidget(cancalButton);
    QVBoxLayout *MainVlayout = new QVBoxLayout(this);
    MainVlayout->addLayout(Hlayout1);
    MainVlayout->addLayout(Hlayout2);
    this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);

}

TreeMenu::TreeMenu(QWidget *parent):QTreeWidget(parent){
    this->setObjectName("TreeMenu");
    this->verticalScrollBar()->setObjectName("TreeMenuVerticl");
    this->horizontalScrollBar()->setObjectName("TreeMenuHorizontal");

    this->setColumnCount(1);
    this->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);

    this->setAutoScroll(true);
    this->header()->setVisible(false);   //隐藏横向表头

    this->setFrameStyle(QFrame::Sunken);
    this->setAnimated(true); //展开折叠动画

    newFileWidget = new NewBulidFile();
    connect(newFileWidget->okButton,SIGNAL(clicked(bool)),this,SLOT(bulidNewFileSlot(bool)));
    connect(newFileWidget->cancalButton,SIGNAL(clicked(bool)),this,SLOT(closeBuildFileSlot(bool)));

    newDirWidget = new NewBuildfolder();
    connect(newDirWidget->okButton,SIGNAL(clicked(bool)),this,SLOT(buildNewDirSlot(bool)));
    connect(newDirWidget->cancalButton,SIGNAL(clicked(bool)),this,SLOT(cancelDirSlot(bool)));
	// 创建右击文件夹的菜单栏
    dirMenu = new QMenu();
    dirMenu->addAction("新建文件");
    dirMenu->addAction("重命名");
    dirMenu->addSeparator();
    dirMenu->addAction("新建文件夹");
    dirMenu->addAction("删除文件夹");
    dirMenu->addAction("在文件夹中查找             ");
    dirMenu->addAction("关闭项目");
	// 创建右击文件的菜单栏
    fileMenu = new QMenu();
    fileMenu->addAction("重命名");
    fileMenu->addAction("删除文件");
    fileMenu->addAction("打开所在文件夹");
    connect(dirMenu,SIGNAL(triggered(QAction*)),this,SLOT(tempActionInformation(QAction*)));
    connect(fileMenu,SIGNAL(triggered(QAction*)),this,SLOT(tempActionInformation(QAction*)));

    connect(this,SIGNAL(itemPressed(QTreeWidgetItem*,int)),this,SLOT(itemPressedSlot(QTreeWidgetItem*,int)));
    connect(this,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(DoubleClickpath(QTreeWidgetItem*,int)));
    connect(this,SIGNAL(collapseItemSignal(const QTreeWidgetItem*)),this,SLOT(collapseItem(const QTreeWidgetItem*)));
}

// 创建文件树的根
void TreeMenu::CreateTopItem(QString path){
    QDir *rootdir = new QDir(path);
    root = new QTreeWidgetItem();
    this->addTopLevelItem(root);
    root->setText(0,rootdir->dirName());
    FindFile(rootdir,root);
    QApplication::processEvents(); //防止界面假死
    root->setExpanded(true);
}
// 创建文件树
void TreeMenu::FindFile(QDir *path,QTreeWidgetItem *parent){
    QApplication::processEvents(); //防止界面假死
    QStringList AllDirName = path->entryList();  //返回所有文件名
    QString PathContent = path->absolutePath();
    for(int i=2;i<AllDirName.size();i++)
    {
        QFileInfo *FileInfo = new QFileInfo(PathContent+"/"+AllDirName[i]);
        if(FileInfo->isFile())
        {
            QTreeWidgetItem *child = new QTreeWidgetItem(parent); //创建对象并添加所属关系
            child->setIcon(0,QIcon(":/new/prefix1/image/appbar.page.bold.png")); //设置Item的图标,也可以通过QSS设置。
            child->setText(0,AllDirName[i]); //设置Item的名字及所扫描到的文件名。
            child->setToolTip(0,PathContent+"/"+AllDirName[i]);
        }
        else if(FileInfo->isDir())
        {
            QDir *NextDir = new QDir(PathContent+"/"+AllDirName[i]); //返回包含文件名的绝对路径。
            QTreeWidgetItem *child = new QTreeWidgetItem(parent);  //创建对象并添加所属关系。
            child->setIcon(0,QIcon(":/new/prefix1/image/appbar.folder.png")); //设置Item的图标,也可以通过QSS设置。
            child->setText(0,AllDirName[i]);  //设置Item的名字及所扫描到的文件名。
            child->setToolTip(0,PathContent+"/"+AllDirName[i]); //鼠标移动到Item上所显示的内容,这里为绝对路径。
            FindFile(NextDir,child);
        }
    }
}
// 双击槽函数检测是文件还是目录
void TreeMenu::DoubleClickpath(QTreeWidgetItem *item, int /*column*/){
    QString absolute_Path = item->toolTip(0);
    QFileInfo *FileInfo = new QFileInfo(absolute_Path);
    this->resizeColumnToContents(0);

    if(FileInfo->isFile())
    {
        // 发送信号量打开文件
        emit showTextSignal(absolute_Path,FileInfo->baseName(),item);
    }
    else{
        // 由于不是文件所以除了执行展开或折叠文件外不再需要执行其他操作,因此此处不需要执行别的操作。
    }
}
// 鼠标右键单击文件或文件夹时所执行的操作
void TreeMenu::itemPressedSlot(QTreeWidgetItem * pressedItem, int column){
    this->resizeColumnToContents(0);
    nowItem = pressedItem;
    nowCol = column;
    if(qApp->mouseButtons() == Qt::RightButton)   //判断是否为右键
    {
        QString absolute_Path = pressedItem->toolTip(0);
        QFileInfo *FileInfo = new QFileInfo(absolute_Path);
        if(FileInfo->isFile()){
            fileMenu->exec(QCursor::pos()); //显示右键菜单栏
        }
        else{
            dirMenu->exec(QCursor::pos());  //显示右键菜单栏
        }
    }
}
// 右击菜单栏执行操作的具体方法
void TreeMenu::tempActionInformation(QAction *act){
    qDebug() << "Item " <<act->text();
    if(act->text()=="关闭项目"){
        QTreeWidgetItem *item = this->currentItem();
        QTreeWidgetItem* parItem=item->parent();
        if(parItem==0)
        {
            delete item;
        }
        else {
            parItem->removeChild(item) ;
            delete item;
        }
    }
    if(act->text() == "删除文件"){
        QTreeWidgetItem *item = this->currentItem();
        delete item;
    }
    if(act->text() == "删除文件夹"){
        QTreeWidgetItem *item = this->currentItem();
        delete item;
    }
    if(act->text() == "重命名"){
        emit renameSignal();
    }
    if(act->text() == "打开所在文件夹"){
        QString path = nowItem->toolTip(0);
        int index=0;
        for(int i=0;i<path.length();i++){
            if(path[i]=="/")
                index=i;
        }
        QString filePath = path.mid(0,index).replace("/","\\");
        QProcess::startDetached("explorer "+filePath);//打开上面获取的目录

    }
    if(act->text() == "新建文件"){
        newFileWidget->setModal(true);
        newFileWidget->show();
    }
    if(act->text()=="新建文件夹"){
        newDirWidget->setModal(true);
        newDirWidget->exec();
    }
}
// 文件夹折叠的实现主要为顶部按钮提供方法,顶部按钮的实现下次再讲
void TreeMenu::buttonCollapseItem(){
    QTreeWidgetItem *t = this->currentItem();
    if(t==0)
        return;
    if(t->childCount()==0){
        QTreeWidgetItem *p = t->parent();
        if(p==0){
            return;
        }
        else{
            emit collapseItemSignal(p); //折叠文件夹
        }
    }
    else{
        emit collapseItemSignal(t);
    }
}
// 创建文件的具体实现
void TreeMenu::bulidNewFileSlot(bool /*flag*/){
    QString fileName = newFileWidget->fileNameEdit->text();
    QString filetype = newFileWidget->fileNameTypeBox->currentText();
    if(fileName==""){
        QMessageBox::warning(this, tr("警告"),
                             tr("文件名不能为空"));
        return;
    }
    QString tempName = fileName+filetype;
    QString path = nowItem->toolTip(0)+"/"+tempName;
    QFile file(path);
    if(file.exists()){
        QMessageBox::warning(this, tr("警告"),
                             tr("文件已存在"));
        return;
    }
    file.open(QIODevice::ReadWrite | QIODevice::Text);
    file.close();
    QTreeWidgetItem *child = new QTreeWidgetItem(nowItem);
    child->setText(0,tempName);
    child->setIcon(0,QIcon(":/new/prefix1/image/appbar.page.bold.png"));
    child->setToolTip(0,path);
    newFileWidget->close();
}
//取消按钮的具体实现
void TreeMenu::closeBuildFileSlot(bool /*flag*/){
    newFileWidget->close();
}

// 创建文件夹的具体实现
void TreeMenu::buildNewDirSlot(bool /*flag*/){
    QString dirName = newDirWidget->fileNameEdit->text();
    if(dirName==""){
        QMessageBox::warning(this, tr("Application"),
                             tr("文件名不能为空"));
        return;
    }
    QString path = nowItem->toolTip(0)+"/"+dirName;
    QDir *temp = new QDir;
    bool exist = temp->exists(path);
    if(exist){
        QMessageBox::warning(this,tr("创建文件夹"),tr("文件夹已经存在!"));
        return;
    }
    temp->mkdir(path);
    QTreeWidgetItem *child = new QTreeWidgetItem(nowItem);
    child->setText(0,dirName);
    child->setIcon(0,QIcon(":/new/prefix1/image/appbar.folder.png"));
    child->setToolTip(0,path);
    newDirWidget->close();
}
// 取消按钮的具体实现
void TreeMenu::cancelDirSlot(bool /*flag*/){
    newDirWidget->close();
}

QSS美化

#TreeMenuVerticl:vertical
{
  width: 10px;
  border:0px solid;
  border-radius: 2px;
  margin: 0px,0px,0px,0px;
  background-color: transparent;
  background:#F5F5F5;
}

#TreeMenuVerticl:vertical:hover
{
  width: 10px;
  border:0px solid;
  margin: 0px,0px,0px,0px;
  background:#F5F5F5;
}

#TreeMenuVerticl::handle:vertical
{
  width: 10px;
  background:#E1E1E1;
  border-radius: 2px;
}

#TreeMenuVerticl::handle:vertical:hover
{
  background:#969696;
  border-radius: 2px;
}


/*-----------------------------------*/

#TreeMenuHorizontal:horizontal{
    height: 10px;
    border:0px solid;
    border-radius: 2px;
    margin: 0px,0px,0px,0px;
    background-color: transparent;
    background:#F5F5F5;
}

#TreeMenuHorizontal:horizontal:hover
{
  height: 10px;
  border:0px solid;
  margin: 0px,0px,0px,0px;
  background:#F5F5F5;
}

#TreeMenuHorizontal::handle:horizontal
{
  height: 10px;
  background:#E1E1E1;
  border-radius: 2px;
}

#TreeMenuHorizontal::handle:horizontal:hover
{
  background:#969696;
  border-radius: 2px;
}


素材
在这里插入图片描述在这里插入图片描述

  • 15
    点赞
  • 89
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
你可以通过继承 QTreeView 类来自定义文件列表视图。 首先,创建一个新的类(例如 CustomTreeView),并将其继承自 QTreeView。然后,在类的构造函数中进行一些初始化设置,如设置文件模型和根节点。 接下来,你可以重写某些父类方法来实现自定义的行为。例如,你可以重写 data() 方法来返回每个单元格的自定义数据,或者重写 dropEvent() 方法来实现拖放操作。 以下是一个简单的示例代码,演示如何自定义文件列表视图: ```cpp #include <QTreeView> #include <QFileSystemModel> class CustomTreeView : public QTreeView { public: CustomTreeView(QWidget *parent = nullptr) : QTreeView(parent) { // 创建文件模型 QFileSystemModel *fileModel = new QFileSystemModel(this); fileModel->setRootPath("/"); // 设置根节点 QModelIndex rootIndex = fileModel->index("/"); setModel(fileModel); setRootIndex(rootIndex); // 设置其他视图选项(可选) setSelectionMode(QAbstractItemView::ExtendedSelection); setDragEnabled(true); setAcceptDrops(true); } QVariant data(const QModelIndex &index, int role) const override { if (role == Qt::DisplayRole) { // 返回自定义显示数据 return "Custom Data"; } return QTreeView::data(index, role); } void dropEvent(QDropEvent *event) override { // 实现拖放操作的逻辑 // ... QTreeView::dropEvent(event); } }; ``` 然后,你可以在主窗口或其他地方使用 CustomTreeView 类来创建自定义的文件列表视图: ```cpp #include <QMainWindow> #include <QVBoxLayout> class MainWindow : public QMainWindow { public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { QWidget *centralWidget = new QWidget(this); QVBoxLayout *layout = new QVBoxLayout(centralWidget); CustomTreeView *treeView = new CustomTreeView(this); layout->addWidget(treeView); setCentralWidget(centralWidget); } }; ``` 这只是一个简单的示例,你可以根据你的需求进一步自定义文件列表视图的行为和外观。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值