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

news2025/1/17 1:47:37

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

新建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());   //菜单弹出位置为鼠标点击位置
            }
    }
}

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

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenHarmony集成OCR三方库实现文字提取

1. 简介 Tesseract(Apache 2.0 License)是一个可以进行图像OCR识别的C库&#xff0c;可以跨平台运行 。本样例基于Tesseract库进行适配&#xff0c;使其可以运行在OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;上&#xff0c;并新增N-API接口供上层应…

[算法] 优先算法(二): 双指针算法(下)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

Rust学习心得

我分享一下一年的Rust学习经历&#xff0c;从书到代码都一网打尽。 关于新手如何学习Rust&#xff0c;我之前在Hacker News上看到了这么一篇教程&#xff1a; 这篇教程与其他教程不同的时&#xff0c;他不是一个速成教程&#xff0c;而是通过自己的学习经历&#xff0c;向需要…

mac安装两个版本谷歌浏览器;在mac运行不同版本的chrome浏览器

场景 正常情况下&#xff0c;mac上只能安装一个版本的chrome浏览器&#xff0c;即使你安装了两个版本的&#xff0c;打开老旧版本时候也会自动切换成最新版的浏览器 故本文主要解决如何下载和在mac运行不同版本的chrome浏览器 文章目录 场景一、下载1.mac本身就有一个最新版ch…

【MySQL】库的操作和表的操作

库的操作和表的操作 一、库的操作1、创建数据库(create)2、字符集和校验规则&#xff08;1&#xff09;查看系统默认字符集以及校验规则&#xff08;2&#xff09;查看数据库支持的字符集&#xff08;3&#xff09;查看数据库支持的字符集校验规则&#xff08;4&#xff09;校验…

网关路由SpringCloudGateway、nacos配置管理(热更新、动态路由)

文章目录 前言一、网关路由二、SpringCloudGateway1. 路由过滤2. 网关登录校验2.1 鉴权2.2 网关过滤器2.3 登录校验2.3.1 JWT2.3.2 登录校验过滤器 3. 微服务从网关获取用户4. 微服务之间用户信息传递 三、nacos配置管理问题引入3.1 配置共享3.1.1 在Nacos中添加共享配置3.1.2 …

Kubectl 的使用——k8s陈述式资源管理

一、kebuctl简介: kubectl 是官方的CLI命令行工具&#xff0c;用于与 apiserver 进行通信&#xff0c;将用户在命令行输入的命令&#xff0c;组织并转化为 apiserver 能识别的信息&#xff0c;进而实现管理 k8s 各种资源的一种有效途径。 对资源的增、删、查操作比较方便&…

MobaXterm下载虚拟机SSH链接超时解决(保姆级踩坑)

文章目录 为啥要用MobaXtermMobaXterm下载打开虚拟机ssh链接ssh连接失败排查linux配置windows配置 到这了&#xff0c;什么都干了&#xff0c;怎么还不成功&#xff1f; 更多相关内容可查看 在一个阳光明媚的下午&#xff0c;开启了无限踩坑的旅程 为啥要用MobaXterm 作为小编…

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

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

解决脚本刷服务器导致卡顿宕机的问题

在互联网服务领域&#xff0c;自动化脚本的不当使用或恶意攻击可能会导致服务器资源被过度消耗&#xff0c;从而引发服务响应缓慢甚至系统崩溃。特别是在电商、游戏、社交平台等领域&#xff0c;这种现象尤为常见。本文将深入探讨脚本刷服的常见形式、其对服务器性能的影响&…

面向对象-----继承

前面向大家介绍了面向对象中的封装性&#xff0c;今天再来向大家介绍面向对象的继承和多态的两大特性。 1.继承 1.1 为什么需要继承&#xff1f; 在java语言中&#xff0c;我们用类来描述世间万物&#xff0c;虽然万物非常复杂&#xff0c;但总有一些共同点&#xff0c;如果…

Java NIO 基础

Java NIO 基础 1. NIO 介绍2. NIO 三大组件2.1 Channel2.1.1 常见的 Channel2.1.2 常用方法 2.2 Buffer2.2.1 常见的 Buffer2.2.2 重要属性2.2.3 常用方法 2.3 Selector2.3.1 四种事件类型 1. NIO 介绍 NIO&#xff08;non-blocking io&#xff09;&#xff1a;非阻塞IO&#…

2024.5.20 学习记录

1、react 原理&#xff08;jsx的本质、事件机制原理、setState和batch Update、组件渲染更新和diff算法、fiber&#xff09; 2、代码随想录贪心刷题

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

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

GPT-4o 引领人机交互新风向的向量数据库Milvus Cloud 成本

成本 AIGC 时代对于冷热储存的呼唤 成本一直是向量数据库获得更广泛使用的最大阻碍之一,这个成本来自两点: 储存,绝大多数向量数据库为了保证低延迟,需要把数据全量缓存到内存或者本地磁盘。在这个动辄百亿量级的AI 时代,意味着几十上百 TB 的资源消耗。 计算,数据需…

OCR版面分析-- PaddleOCR(python 文档解析提取)

1. 创建新的conda环境 # 在命令行输入以下命令&#xff0c;创建名为paddle_env的环境 # 此处为加速下载&#xff0c;使用清华源 conda create --name paddle_env python3.8 --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ # 这是一行命令2. 激活刚创建…

全球视频会议软件巨头Zoom,率先引入后量子端到端加密

5月21日&#xff0c;Zoom Video Communications公司宣布&#xff0c;后量子端到端加密&#xff08;E2EE&#xff09;现已面向全球推出&#xff0c;适用于Zoom Workplace。目前&#xff0c;Zoom已将该功能加入Zoom Meetings&#xff0c;稍后将扩展至Zoom Phone和Zoom Rooms。 图…

数据中心大型AI模型网络需求

数据中心大型AI模型网络需求 随着Transformer的崛起和2023年ChatGPT的大规模应用&#xff0c;业界逐渐形成共识&#xff1a;遵循一定的规模效应原则&#xff0c;增加模型参数量能够显著提升模型性能。特别是在参数数量级跃升至数百亿乃至更高时&#xff0c;大型AI模型在语言理…

20232803 2023-2024-2 《网络攻防实践》实践十报告

目录 1. 实践内容1.1 SEED SQL注入攻击与防御实验1.2 SEED XSS跨站脚本攻击实验(Elgg) 2. 实践过程2.1 SEED SQL注入攻击与防御实验2.1.1 熟悉SQL语句2.1.2 对SELECT语句的SQL注入攻击2.1.3 对UPDATE语句的SQL注入攻击2.1.4 SQL对抗 2.2 SEED XSS跨站脚本攻击实验(Elgg)2.2.1 发…

超前预热|博睿数据将应邀出席双态IT用户大会,分享《构建云原生时代的一体化智能可观测性》

5月31日&#xff0c;第十二届双态IT用户大会将于成都盛大开幕&#xff0c;此次大会由DCMG和双态IT论坛联合主办&#xff0c;聚焦“信创时代的组织级云原生能力建设”和“组织级云原生运维能力建设”两大会议主题&#xff0c;旨在推动双态IT落地与创新&#xff0c;为企业数字化转…