导入项目

之前我们创建一个相册项目是通过向导设置项目名称和路径,再选择指定文件夹内容导入到我们的项目路径,并且copy文件的。这次要做的功能是直接打开一个文件夹,将文件夹内容直接展示在左侧目录树中。

连接打开信号

在mainwindow构造函数里添加打开项目的信号和槽函数

    //打开项目动作
    QAction * act_open_pro = new QAction(QIcon(":/icon/openpro.png"), tr("打开项目"),this);
    act_open_pro->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O));
    menu_file->addAction(act_open_pro);
    //连接打开项目的槽函数
    connect(act_open_pro, &QAction::triggered, this, &MainWindow::SlotOpenPro);
    connect(this, &MainWindow::SigOpenPro, pro_tree_widget, &ProTreeWidget::SlotOpenPro);

当我们点击打开项目时触发SlotOpenPro函数

void MainWindow::SlotOpenPro(bool)
{
    QFileDialog file_dialog;
    file_dialog.setFileMode(QFileDialog::Directory);
    file_dialog.setWindowTitle("选择导入的文件夹");

    file_dialog.setDirectory(QDir::currentPath());
    file_dialog.setViewMode(QFileDialog::Detail);

    QStringList fileNames;
    if (file_dialog.exec()){
         fileNames = file_dialog.selectedFiles();
    }

    if(fileNames.length() <= 0){
          return;
    }

      QString import_path = fileNames.at(0);
      qDebug() << "import_path is " << import_path << endl;
      emit SigOpenPro(import_path);
}

该函数打开一个文件对话框,根据选择的文件夹返回我们要打开的路径,然后将这个路径用SigOpenPro信号发送出去。 会触发ProTreeWidget的SlotOpenPro函数

void ProTreeWidget::SlotOpenPro(const QString& path)
{
    if(_set_path.find(path) != _set_path.end()){
        qDebug() << "file has loaded" << endl;
        return;
    }

    _set_path.insert(path);
    int file_count = 0;
    QDir pro_dir(path);
    const QString& proname = pro_dir.dirName();

    _thread_open_pro = std::make_shared<OpenTreeThread>(path, file_count, this,nullptr);
    _thread_open_pro->start();

    _open_progressdlg = new QProgressDialog(this);

    //连接更新进度框操作
    connect(_thread_open_pro.get(), &OpenTreeThread::SigUpdateProgress,
            this, &ProTreeWidget::SlotUpOpenProgress);

    connect(_thread_open_pro.get(), &OpenTreeThread::SigFinishProgress, this,
            &ProTreeWidget::SlotFinishOpenProgress);

    _open_progressdlg->setWindowTitle("Please wait...");
    _open_progressdlg->setFixedWidth(PROGRESS_WIDTH);
    _open_progressdlg->setRange(0, PROGRESS_MAX);
    _open_progressdlg->exec();

}

上述逻辑中,我们创建了一个进度对话框,以及一个线程OpenTreeThread,并让他们通信,更新进度框进度以及完成情况。

设计打开逻辑线程类

线程构造函数

OpenTreeThread::OpenTreeThread(const QString &src_path, int &file_count,
                               QTreeWidget *self, QObject *parent):
    QThread (parent),_bstop(false),_src_path(src_path),_file_count(file_count)
    ,_self(self),_root(nullptr)
{

}

_bstop表示是否终止线程。 _src_path表示打开的文件路径。 _file_count表示文件数量。 _root表示ProTreeItem类型的根节点。 _self表示ProTreeWidget类型的对象。

程序启动后执行run函数

void OpenTreeThread::run()
{
    OpenProTree(_src_path,_file_count,_self);
    if(_bstop&&_root){
        auto path = dynamic_cast<ProTreeItem*>(_root)->GetPath();
        auto index = _self->indexOfTopLevelItem(_root);
        delete _self->takeTopLevelItem(index);
        QDir dir(path);
        dir.removeRecursively();
        return;
    }

    emit SigFinishProgress(_file_count);
}

run函数内调用OpenProTree导入逻辑生成目录树,然后判断_bstop是否为真并且root有效,说明取消了导入操作,所以删除目录树。 当执行完导入操作后发送完成信号SigFinishProgress。

void OpenTreeThread::OpenProTree(const QString &src_path,
                                int &file_count, QTreeWidget *self)
{
    //创建根节点
    QDir src_dir(src_path);
    auto name = src_dir.dirName();
    auto * item = new ProTreeItem(self, name, src_path,  TreeItemPro);
    item->setData(0,Qt::DisplayRole, name);
    item->setData(0,Qt::DecorationRole, QIcon(":/icon/dir.png"));
    item->setData(0,Qt::ToolTipRole, src_path);
    _root = item;

    //读取根节点下目录和文件
    RecursiveProTree(src_path,file_count,self,_root,item, nullptr);
}

OpenProTree创建了根节点,然后调用了递归函数RecursiveProTree递归创建子节点。

void OpenTreeThread::RecursiveProTree( const QString &src_path, int &file_count, QTreeWidget *self,
                                       QTreeWidgetItem *root, QTreeWidgetItem *parent,QTreeWidgetItem* preitem)
{
    QDir src_dir(src_path);
    //设置文件过滤器
    QStringList nameFilters;
    src_dir.setFilter(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot);//除了目录或文件,其他的过滤掉
    src_dir.setSorting(QDir::Name);//优先显示名字
    QFileInfoList list = src_dir.entryInfoList();
    qDebug() << "list.size " << list.size() << endl;
    for(int i = 0; i < list.size(); i++){
        if(_bstop){
            return;
        }
        QFileInfo fileInfo = list.at(i);
        bool bIsDir = fileInfo.isDir();
        if (bIsDir)
        {
            if(_bstop){
                return;
            }
            file_count++;
            emit SigUpdateProgress(file_count);
            auto * item = new ProTreeItem(_root, fileInfo.fileName(),
                                          fileInfo.absoluteFilePath(), _root,TreeItemDir);
            item->setData(0,Qt::DisplayRole, fileInfo.fileName());
            item->setData(0,Qt::DecorationRole, QIcon(":/icon/dir.png"));
            item->setData(0,Qt::ToolTipRole, fileInfo.absoluteFilePath());

            RecursiveProTree(fileInfo.absoluteFilePath(), file_count,
                             self,root,item, preitem);

         }else{
            if(_bstop){
                return;
            }

            const QString & suffix = fileInfo.completeSuffix();
            if(suffix != "png" && suffix != "jpeg" && suffix != "jpg"){
                qDebug() << "suffix is not pic " << suffix << endl;
                continue;
            }

            file_count++;
             emit SigUpdateProgress(file_count);

            auto * item = new ProTreeItem(parent, fileInfo.fileName(),
                                          fileInfo.absoluteFilePath(), root,TreeItemPic);
            item->setData(0,Qt::DisplayRole, fileInfo.fileName());
            item->setData(0,Qt::DecorationRole, QIcon(":/icon/pic.png"));
            item->setData(0,Qt::ToolTipRole, fileInfo.absoluteFilePath());

            if(preitem){
                auto* pre_proitem = dynamic_cast<ProTreeItem*>(preitem);
                pre_proitem->SetNextItem(item);
            }

            item->SetPreItem(preitem);
            preitem = item;
        }
    }

    emit SigFinishProgress(file_count);
}

这样完成了打开一个文件夹生成项目的功能。

幻灯片SlideShowDlg类的ui设计

我们创建一个名字为SlideShowDlg设计师界面类,然后在ui文件里添加两个QWidget,分别命名为preShow和slideShow。 1 将SlideShowDlg设置为垂直布局,将拉伸比例设置为7比1,这样整体的布局被分为两部分,上部分为slideShow,下部分为preShow,slideShow设置为网格布局,preShow设置为垂直布局。 2 在slideShow里添加两个固定宽度为80像素的widget(slidenextwid和slideprewid),这个两个widget设置为垂直布局,分别在widget里添加button(slidenextBtn和slidepreBtn), 3 在slideShow里添加一个水平布局放在右上角,然后在该布局里添加两个按钮(closeBtn和playBtn)。 4 在slideShow里添加一个widget(命名为picAnimation)设置为网格布局 5 在preShow中添加一个高度固定为120的widget,让其宽度自适应,该widget设置为网格布局,在该widget内部添加一个widget命名为preListWidget,主要用来展示预览图。 幻灯片界面ui如下 https://cdn.llfc.club/1674979781177.jpg 布局信息如下 https://cdn.llfc.club/1674986967186.jpg 因为布局信息里对widget提升了,比如PicAnimationWid,PicButton,PreListWid等,交给后一篇讲述。

源码链接

源码链接 https://gitee.com/secondtonone1/qt-learning-notes

results matching ""

    No results matching ""