Qt快速入门到熟练(电子相册项目(二))

        上一节我们成功实现了创建项目的向导界面的开发,这节我们继续去实现电子相册的其他功能。

新建DirTreeWidget类

·        还记得在Qt快速入门到熟练(电子相册项目(一))-CSDN博客里面,我们是在QDockWidget中添加了一个treeWidget作为以后显示目录树的空间。实际上我们完全可以在mainwindow中实现对treeWidget代码的编写,但是我们考虑到之后可能会添加其他的功能,吧代码全部写在主窗口函数中可能会导致一个cpp文件中代码过于臃肿,对于以后的排错也相对来说比骄傲苦难。所以我们决定新建一个DirTreeWidget类作为对代码的实现。然后在ui界面中将之前拖拽生成的treeWidget的父类提升为DirTreeWidget。

重构SlotCreatePro

        还记得这个槽函数吗,之前我们在Wizard类里面实现了创建项目的槽函数,但是在这个槽函数中我们当时保留了一个connect函数,就是在向导完成后我们需要将由创建项目向导创建出来的文件夹显示到treeWidget里面,所以我们现在就需要连接到刚刚新建的DirTreeWidget里面的AddDirToTree这个槽函数,但是这时我们就会发现由于我们的treeWidget是在主窗口ui中创建的,当我们new DirTreeWidget的时候,如果槽函数在Wizard类里面,我们的构造函数想要继承父类就比较麻烦,想要将new DirTreeWidget的父类设置到主窗口则需要包含mainwindow.h,但是这样就会造成不同头文件的互引用,可能会产生不必要的错误。一般来说我习惯与在主窗口包含其他组件的头文件,但是其他组件的头文件中不要包含主窗口。

        所以经过思考,我最后还是把这个创建项目的槽函数放到了mainwindow里面。实际上创建项目这一过程的产生就是在向导对话框时产生的,逻辑上放在Wizard类中是比较合适的,但是有时候可以做出一些让步,这会让程序变得简单。如果实在是想把槽函数放在Wizard类也不是不行,只不过就需要我在此基础上新建一个设计师类把主窗口的treeWidget给承接过来。

        反正对于这个问题还有许多解决办法,我这里只是展示了一种我比较喜欢的方法,大家完全可以采取其他方法去解决这个问题。     

void MainWindow::SlotCreatePro(bool){
    qDebug() << "slot create pro triggered" << endl;
    Wizard wizard(this);
    wizard.setWindowTitle(tr("创建项目"));
    auto *page = wizard.page(0);
    page->setTitle(tr("设置项目配置"));
    QVBoxLayout *layout = new QVBoxLayout(page);
    layout->setContentsMargins(200, 100, 50, 50);
    layout->addWidget(page);
    //连接信号和槽
    dirtreewidget = new DirTreeWidget(ui->treeWidget);
//    ui->verticalLayout->addWidget(dirtreewidget);
    connect(&wizard, &Wizard::SigProSettings, dirtreewidget, &DirTreeWidget::AddDirToTree);


    wizard.show();
    wizard.exec();
    delete layout;
    //断开所有信号
//    disconnect(&wizard);
}

 显示创建的文件夹

        在设置向导时我们通过wizardPage1中的GetProSettings函数获取到lineEdit中的项目名称和项目路径,然后在wizard点击完成时触发done函数,进而发送信号触发DirTreeWidget的AddDirToTree函数了,从而生成一个项目目录的item。

        下面我们就来设计AddDirToTree函数的实现,这里为了检测生成的路径是否重名,我们使用set来进行路径的管理,函数将获取到的路径传进来,然后通过set进行存储,每次存储前进行重名检测,如果set中已经有这个路径,那么程序就会直接退出。如果没有重名,就进行创建创建文件夹完毕以后,需要在treeWidget显示出来,每一个树的结点都是一个Item。所以我们需要再新建一个DirTreeItem,这样方便我们自定义自己新的item节点。

void DirTreeWidget::AddDirToTree(const QString &name, const QString &path)
{
    qDebug() << "DirTreeWidget::AddDirToTree name is " << name << " path is " << path << endl;
    QDir dir(path);
    QString file_path = dir.absoluteFilePath(name);
    //检测重名,判断路径和名字都一样则拒绝加入
    if(_set_path.find(file_path) != _set_path.end()){
        qDebug() << "file has loaded" << endl;
        return;
    }
    //构造项目用的文件夹
    QDir pro_dir(file_path);
    //如果文件夹不存在则创建
    if(!pro_dir.exists()){
        bool enable = pro_dir.mkpath(file_path);
        if(!enable){
            qDebug() << "pro_dir make path failed" << endl;
            return;
        }
    }

    _set_path.insert(file_path);
    auto * item = new DirTreeItem(this, name, file_path, TreeItem);
    item->setData(0,Qt::DisplayRole, name);
    item->setData(0,Qt::DecorationRole, QIcon(":/icon/dir.png"));
    item->setData(0,Qt::ToolTipRole, file_path);
    this->show();
}

创建DirTreeItem类

        关于DirTreeItem类,我们写一下他的构造函数,对于Item有可能是相对来说可以叫做根节点,它们是直接使用QTreeWidget 作为父类,然后还需要三个参数,分别是名字,路径和类型。另一个构造函数我们要考虑子目录,往往是有一个QTreeWidgetItem 作为父类,这样的参数不仅需要name,path,type,而且需要知道这个Item的根节点是是谁。

参考上面声明的两个构造函数,我们还需要三个成员变量   :

QString _path;
QString _name;
QTreeWidgetItem* _root;

#ifndef DIRTREEITEM_H
#define DIRTREEITEM_H
#include <QTreeWidgetItem>
class DirTreeItem : public QTreeWidgetItem
{
//    Q_OBJECT
public:
    DirTreeItem(QTreeWidget *view, const QString & name, const QString & path,int type = Type);
    DirTreeItem(QTreeWidgetItem *parent, const QString & name, const QString & path,
                QTreeWidgetItem* root, int type = Type);
private:
    QString _path;
    QString _name;
    QTreeWidgetItem* _root;

};

#endif // DIRTREEITEM_H
DirTreeItem::DirTreeItem(QTreeWidget *view, const QString &name, const QString &path, int type):
                        QTreeWidgetItem (view, type),_path(path),_name(name)
{

}

DirTreeItem::DirTreeItem(QTreeWidgetItem *parent, const QString &name, const QString &path, QTreeWidgetItem *root, int type):
                        QTreeWidgetItem(parent,type),_path(path),_name(name),_root(root)
{

}

        现在我们来build我们的项目,点击新建项目,输入项目名称,点击完成,可以看到在侧边栏出现了我们刚刚创建的项目的文件夹目录。

右键显示菜单

        现在我们已经创建了一个新的项目,但是现在这个项目里面并没有内容,我们所要做的是一款电子相册,那么如何向这个项目目录里面添加文件(图片)呢,首先是需要有能够互动的选项。就比如这样:

那么首先我们线要创建这四个Action,然后让它们在我们鼠标点击右键的时候显示出来。

DirTreeWidget::DirTreeWidget(QWidget *parent):QTreeWidget (parent)
{
    //隐藏表头
    this->header()->hide();
    connect(this, &DirTreeWidget::itemPressed, this, &DirTreeWidget::SlotItemPressed);
//    connect(this, &DirTreeWidget::itemDoubleClicked, this, &DirTreeWidget::SlotDoubleClickItem);
    _action_import = new QAction(QIcon(":/icon/import.png"),tr("导入文件"), this);
    _action_setstart = new QAction(QIcon(":/icon/core.png"), tr("设置活动项目"),this);
    _action_closepro = new QAction(QIcon(":/icon/close.png"), tr("关闭项目"), this);
    _action_slideshow = new QAction(QIcon(":/icon/slideshow.png"), tr("轮播图播放"),this);
}

        在DirTreeWidget类的构造函数里,我们设置一个信号与槽,DirTreeWidget类继承自QTreeWidget,在QTreeWidget里面有一个信号函数itemPressed,他的作用是当用户在小部件内按下鼠标按钮时,就会发出这个信号。然后我们编写对应的槽函数。

        在槽函数里,我们首先要判断鼠标点击事件的来源,判断是否为右键,如果是右键,那么就会创建一个menu对象,再进行Item类型的判断,因为我们的Item只有是文件夹类型的才会显示出下面的菜单列表,如果是其他类型,菜单显示的内容也会不同。

void DirTreeWidget::SlotItemPressed(QTreeWidgetItem *pressedItem, int column)
{
    qDebug() << "ProTreeWidget::SlotItemPressed" << endl;
    if(QGuiApplication::mouseButtons() == Qt::RightButton)   //判断是否为右键
        {
            QMenu menu(this);
            qDebug() << "menu addr is " << &menu << endl;
            int itemtype = (int)(pressedItem->type());
            if (itemtype == TreeItem)
            {
                _right_btn_item = pressedItem;
                menu.addAction(_action_import);
                menu.addAction(_action_setstart);
                menu.addAction(_action_closepro);
                menu.addAction(_action_slideshow);
                menu.exec(QCursor::pos());   //菜单弹出位置为鼠标点击位置
            }
    }
}

        到这里我们完成了右键显示菜单的相关内容,之后我们将会继续文件夹导入功能的编写,谢谢大家观看,我们一起学习。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/633113.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

App Inventor 2 TaifunBattery 电池管理器拓展,获取电量、电池容量

TaifunBattery 电池管理器拓展 电池管理器扩展。所需权限&#xff1a;无 demo效果图&#xff1a; 属性 返回当前健康常量。 可能的值有&#xff1a;冷(cold)、死(dead)、好(good)、过热(overheat)、过压(over voltage)、未知(unknown)、未指定故障(unspecified failure)。 返…

海山数据库(He3DB)数据仓库发展历史与架构演进:(一)传统数仓

从1990年代Bill Inmon提出数据仓库概念后经过四十多的发展&#xff0c;经历了早期的PC时代、互联网时代、移动互联网时代再到当前的云计算时代&#xff0c;但是数据仓库的构建目标基本没有变化&#xff0c;都是为了支持企业或者用户的决策分析&#xff0c;包括运营报表、企业营…

最近真的忙炸了。。

大家好&#xff0c;我是鱼皮&#xff0c;每隔一段时间&#xff0c;我都会写一段自己的工作复盘。最近这个月的主题就是 “忙炸了”&#xff01;基本上只要睁眼的时间&#xff0c;基本都是在工作&#xff0c;以至于眼药水都怼上了。 简单分享一下我最近在做的一些事情吧。 1、…

docker 指定jdk11镜像执行jar

dockerfile :下载jdk11 并将上传的jar 放入jdk11容器/root&#xff0c;改名为app.jar vi dockerfile 。。。。内容见下图 # 构建jdk11镜像 docker build -t demo . # 也可以通过jdk11镜像&#xff08;前提有jdk11镜像&#xff09;外挂载目录方式运行jar docker run --name d…

简单介绍十款可以免费使用的API测试工具

API开发应该是后端开发最常见的工作&#xff0c;而调试和测试API是非常关键的&#xff0c;这篇文章简单介绍几款常用的工具以供大家参考。 SoapUI SoapUI是很老牌的工具的&#xff0c;在之前Webservice盛行的时候经常会用到。 现在官方推出了Pro版本的ReadyAPI&#xff0c;但要…

MacOS安装Docker-Compose

方法一 按照百度的方法进行安装&#xff0c;我大致复制一下百度的方法 1.确保您已经安装了Docker Desktop。 2.下载Docker Compose二进制文件。 3.将二进制文件移动到/usr/local/bin目录。 4.更改二进制文件的权限&#xff0c;使其可执行。 以下是具体的命令&#xff1a;…

使用TensorFlow Lite Micro流程记录(带源码)

文章目录 0 关于tflite micro1 克隆仓库2 编译静态库3 模型转换4 编写工程5 编写demo5.1 进行算子注册 5.2 推理过程6 debug记录6.1 缺少算子 6.2 注册表太小6.3 段错误6.4 进一步减小库体积 7 实际部署 0 关于tflite micro 关于tflite micro在这里接不做过多介绍了&#xff0c…

vue3结合element-plus之如何优雅的使用表单组件

背景 在日常开发中,我们会经常使用 element-ui 或者是 antdesign 或者是 element-plus 等组件库实现搜索功能 这里就需要用到相关表单组件 下面就以 element-plus 为例,我们实现一个搜索功能的组件,并且随着屏幕尺寸的变化,其布局也会跟随变化 最终大致效果如下: 这里…

MySql:多表设计-关联查询

目录 多表设计 代码 运行 数据库设计范式 设计三范式 1、第一范式&#xff1a; 2、第二范式&#xff1a; 3、第三范式&#xff1a; 多表设计_关联查询 外键 外键约束 代码 运行 注意&#xff1a; 应用 代码 运行 代码 运行 关联查询 含义&#xff1a; …

Android14之Binder调试(二百一十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

服务器数据恢复—服务器正常断电重启后raid信息丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 一台某品牌DL380 G4服务器&#xff0c;服务器通过该服务器品牌smart array控制器挂载了一台国产的磁盘阵列&#xff0c;磁盘阵列中有一组由14块SCSI硬盘组建的RAID5。服务器安装LINUX操作系统&#xff0c;搭建了NFSFTP&#xff0c;作为内部文件…

【LeetCode】【1】两数之和(1141字)

文章目录 [toc]题目描述样例输入输出与解释样例1样例2样例3 提示进阶Python实现哈希表 个人主页&#xff1a;丷从心 系列专栏&#xff1a;LeetCode 刷题指南&#xff1a;LeetCode刷题指南 题目描述 给定一个整数数组nums和一个整数目标值target&#xff0c;请在该数组中找出…

传感器通过Profinet转Modbus网关与PLC通讯在生产线的应用

Profinet转Modbus&#xff08;XD-MDPN100/300&#xff09;网关可视作一座桥梁&#xff0c;能够实现Profinet协议与Modbus协议相互转换&#xff0c;支持Modbus RTU主站/从站&#xff0c;并且Profinet转Modbus网关设备自带网口和串口&#xff0c;既可以实现协议的转换&#xff0c…

【Java基础】IO流(4) —— 转换流、打印流

【Java基础】IO流(1) —— 简介 【Java基础】IO流(2) —— 字符流 【Java基础】IO流(3) —— 字节流 【Java基础】IO流(4) —— 转换流、打印流 【Java基础】IO流(5) —— 序列流、内存流 【Java基础】IO流(6) —— 随机访问文件流、数据流 转换流 InputStreamReader 是字节输…

VUE H5字体在安卓手机偏上解决

安卓手机展示样式,数字偏上,展示效果如图: 项目内添加新字体,引用新字体 vue 项目需要引入字体的话, 可以移步到这篇文章(无需下载依赖包)Vue3中引入外部自定义字体 项目文件assets内创建font文件夹, 粘贴你想用的字体, 创建对应的css文件; scss代码: font-face {/* 自定义的…

前端学习-day08

文章目录 01-相对定位02-绝对定位03-绝对定位居中04-固定定位05-堆叠顺序06-CSS精灵-基本使用07-案例-京东服务08-字体图标10.垂直对齐方式11-过度12-透明度13-光标类型14-轮播图 01-相对定位 <!DOCTYPE html> <html lang"en"> <head><meta ch…

k8s 声明式资源管理

一、资源配置清单的管理 1.1 查看资源配置清单 声明式管理方法&#xff1a; 1.适合于对资源的修改操作 2.声明式资源管理方法依赖于资源配置清单文件对资源进行管理 资源配置清单文件有两种格式&#xff1a;yaml&#xff08;人性化&#xff0c;易读&#xff09;&#xff0c;j…

高性能负载均衡的分类及架构分析

如何选择与部署适合的高性能负载均衡方案&#xff1f; 当单服务器性能无法满足需求&#xff0c;高性能集群便成为提升系统处理能力的关键。其核心在于通过增加服务器数量&#xff0c;强化整体计算能力。而集群设计的挑战在于任务分配&#xff0c;因为无论在哪台服务器上执行&am…

【C++初阶】--- C++入门(上)

目录 一、C的背景及简要介绍1.1 什么是C1.2 C发展史1.3 C的重要性 二、C关键字三、命名空间2.1 命名空间定义2.2 命名空间使用 四、C输入 & 输出 一、C的背景及简要介绍 1.1 什么是C C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&…

看看汉朝有庙号的七位皇帝,你就知道含金量有多高?

汉朝拥有庙号的七位皇帝你们知道是谁吗&#xff1f; 相比于后世皇帝人手一个庙号的景象&#xff0c;汉朝皇帝庙号的使用是相当严谨的。很多原本拥有庙号的皇帝&#xff0c;最后因为功绩不多或者无功无德&#xff0c;最终被废除庙号。因此&#xff0c;汉朝谨遵“祖有功宗有德”…