当前位置: 首页 > news >正文

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

        经过一段时间的学习,相信大家对QT的基本用法都有所了解,从这篇文章开始,我准备记录一下电子相册的项目的一个学习过程。

实现项目创建功能

        对于这个电子相册的项目,我并没有在一开始就把所有可能用到的功能模块去事无巨细的考虑周全,我采用的方式是写到哪里我们在此基础上在添加功能,这样的好处是可以简化思维逻辑构建的复杂程度,避免在项目初期就由于考虑过多内容逻辑混乱无从下手。

新建mainwindow的项目

        不管我们做什么项目,首先需要一个主界面,在主界面的基础上我们进行功能的改进和模块的添加。这里我新建一个mainwindow的项目,不使用之前我们常用的Widget是因为mainwindow的项目自带菜单栏,可以更快构建我们项目的主要功能。

添加菜单栏

        新建mainwindow项目完成后,我们就需要在菜单栏中添加我们需要用到的菜单,刚开始我们只需要文件和设置两个选项,在文件列表里面需要添加创建文件和打开文件,设置里面可以暂时不用添加,也可以添加一个背景音乐的选项作为临时凑数。

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);
//    ui->dockWidget->header()->hide();//创建菜单栏QMenu * menu_file = menuBar()->addMenu(tr("文件(&F)"));//创建项目动作QAction * act_create_pro = new QAction(QIcon(":/icon/createpro.png"), tr("创建项目"),this);act_create_pro->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));menu_file->addAction(act_create_pro);//打开项目动作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);//创建设置菜单QMenu * menu_set = menuBar()->addMenu(tr("设置(&S)"));//设置背景音乐动作QAction * act_music = new QAction(QIcon(":/icon/music.png"), tr("背景音乐"),this);act_music->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));menu_set->addAction(act_music);}

为主窗口添加QDockWidget

        为实现一个电子相册,我们需要一个能够显示文件和图片列表的一个窗口,这里我选择使用一个QDockWidget来作为显示文件列表的窗口,然后在QDockWidget中添加treeWidgetlabel作为显示列表的容器,然后把QDockWidget设置为NoDockWidgetArea,来限制其可停靠的区域,并且取消其最大化和关闭窗口选项。

添加QSS

        观察上方运行结果,可以发现我的界面和你们的可能有些不同,我的界面是经过界面美化过的。在QT中界面美化一般都是通过编写QSS文件,然后在主函数调用的方式来完成界面美化,现在我们就来编写一下暂时所要用到的QSS条目:

创建一个QSS文件将其命名为style.qss

/*mainwindow 样式*/
MainWindow {/* 背景色 */background-color:rgb(46,47,48);
}/*菜单栏基本样式*/
QMenuBar{color:rgb(231,231,231);background-color:rgb(46,47,48);
}/*菜单基本样式*/
QMenu{color:rgb(231,231,231);background-color:rgb(55,55,55);
}/* 菜单栏选中条目时 */
QMenuBar::item:selected {background-color:rgb(80,80,80);
}/*菜单选中条目*/
QMenu::item:selected {background-color:rgb(39,96,154);
}QDockWidget:title
{background-color:rgb(46,47,48);
}/*为QDockWidget添加边框*/
QDockWidget>QWidget
{border-color: #9F9F9F;border-style: solid;border-width: 1px 1px 1px 1px;padding-right: 10px;
}QDockWidget QLabel#label {color: rgb(231,231,231);border-color: #9F9F9F;border-style: dotted;border-width: 0 0 1px 0;padding-bottom: 10px;margin-bottom: 5px;
}QTreeView {color:rgb(231,231,231);background-color:rgb(46,47,48);border: 0px;
}QWizard {color:rgb(231,231,231);background-color:rgb(46,47,48);
}QWizard QLabel#tips {color: red;
}

        那么我们创建的qss文件该存放到哪里呢,不错qss文件和其他资源文件一样,都可以存放到我们的资源文件里面。所以我们创建一个QT资源文件,把创建好的qss文件添加进去。有些读者可能注意到了我在添加菜单栏的时候同时为它们设置了QIcon,这里面所用到的图片我一样是添加到了资源文件里面,只不过在之前没有明说,你们也可以选择自己喜欢的QIcon图片。

添加完成后现在我的资源文件的目录如下:

        上面我们说过,qss需要在主函数调用才能真正配置成功,所以下面我们就需要在主函数里面把qss里面的格式给它配置到我们的Qt程序中:

int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;QFile qss(":/style/style.qss");if(qss.open(QFile::ReadOnly)){qDebug("open qss success");QString style = QLatin1String(qss.readAll());a.setStyleSheet(style);qss.close();}else{qDebug("Open failed");}w.show();return a.exec();
}

 在mainwindow.cpp中添加槽函数

        添加两个connect,在菜单文件中有两个QAction,针对这个两个QAction分别编写连接创建项目槽函数和连接打开项目的槽函数。

    //连接创建项目槽函数wizard = new Wizard(this);connect(act_create_pro, &QAction::triggered, wizard, &Wizard::SlotCreatePro);//连接打开项目的槽函数connect(act_open_pro, &QAction::triggered, this, &MainWindow::SlotOpenPro);//connect(this, &MainWindow::SigOpenPro, pro_tree_widget, &ProTreeWidget::SlotOpenPro);

创建向导类

点击创建项目,需要弹出一个向导界面,对创建项目进行配置引导。

所以我们点击添加新文件,选择Qt设计师界面类,选择界面模板为QWizard

        Wizard类ui自带两个QWizardPage,所以我们完全可以不用单独新建不同的QWizardPage类,但是对于Wizard类没有办法直接调用QWizardPage中registerField函数注册名为 "proPath" 的字段,并将其与 ui->LineEdit 组件相关联。所以对于不需要使用QWizardPage中函数的页面,无需新建QWizardPage类。

        我们在向导首页面需要设置项目的name和path,所以我们还要新建一个QWizardPage设计类,将其命名为WizardPage1。设置界面为如图所示

        在Wizard类的wizard.ui里面对wizardPage1提升为我们刚才新建的WizardPage1类,这样我们在wizardPage1.ui里面的设计都会继承到Wizard类的wizard.ui里面。

添加创建项目槽函数

        之前在mainwindow里面我们连接了一个向导类的槽函数SlotCreatePro,这里我们着手将其实现出来,

void Wizard::SlotCreatePro(bool){qDebug() << "slot create pro triggered" << endl;
//    Wizard wizard(this);this->setWindowTitle(tr("创建项目"));
//   auto *page = this->page(0);ui->wizardPage1->setTitle(tr("设置项目配置"));QVBoxLayout *layout = new QVBoxLayout(ui->wizardPage1);layout->setContentsMargins(10, 200, 10, 10);layout->addWidget(ui->wizardPage1);//连接信号和槽//connect(&wizard, &Wizard::SigProSettings, dynamic_cast<ProTree*>(_protree),&ProTree::AddProToTree);this->show();this->exec();
//    disconnect(&wizard);
}

        现在我们已经初步实现了向导界面的框架,之后我们只需要编写首页面的处理逻辑,本次的文章就完满完成。

进行WizardPage1逻辑编写

        将两个lineEdit注册为wizard的field,保证两个lineEdit是空的时候无法点击下一步,将QLineEdit的textEdited信号和WizardPage1的completeChanged信号连接起来,这样在lineEdit编辑的时候就会发送textEdited信号,进而触发WizardPage1发送completeChanged信号。
setClearButtonEnabled设置为true可以在lineEdit输入数据后显示清除按钮,直接清除已录入的字符。
        completeChanged信号是从WizardPage1的基类QWizardPage类继承而来的。completeChanged信号发出后会触发QWizardPage类的isComplete函数。

WizardPage1::WizardPage1(QWidget *parent) :QWizardPage(parent),ui(new Ui::WizardPage1)
{ui->setupUi(this);registerField("proPath", ui->lineEdit_2);registerField("proName", ui->lineEdit);connect(ui->lineEdit, &QLineEdit::textEdited, this, &WizardPage1::completeChanged);connect(ui->lineEdit_2, &QLineEdit::textEdited, this, &WizardPage1::completeChanged);QString curPath = QDir::currentPath();ui->lineEdit_2->setText(curPath);ui->lineEdit_2->setCursorPosition( ui->lineEdit_2->text().size());ui->lineEdit->setClearButtonEnabled(true);ui->lineEdit_2->setClearButtonEnabled(true);
}

为了实现特定的判断,我们重写isComplete函数。这样我们就能判断文件夹是否合理以及是否已经有项目路径了。
可以根据不满足的条件设置tips提示用户。

bool WizardPage1::isComplete() const
{if(ui->lineEdit->text() == "" || ui->lineEdit_2->text() == ""){return false;}//判断是否文件夹是否合理QDir dir(ui->lineEdit_2->text());if(!dir.exists()){//qDebug()<<"file path is not exists" << endl;ui->tips->setText("project path is not exists");return false;}//判断路径是否存在QString absFilePath = dir.absoluteFilePath(ui->lineEdit->text());
//    qDebug() << "absFilePath is " << absFilePath;QDir dist_dir(absFilePath);if(dist_dir.exists()){ui->tips->setText("project has exists, change path or name!");return false;}ui->tips->setText("");return QWizardPage::isComplete();
}

为浏览按钮添加点击后选择文件夹操作,在wizardPage1.ui文件里右键点击浏览按钮,选择转到槽,QT会为我们生成槽函数

void WizardPage1::on_pushButton_clicked()
{QFileDialog file_dialog;file_dialog.setFileMode(QFileDialog::Directory);file_dialog.setWindowTitle("选择导入的文件夹");auto path = QDir::currentPath();file_dialog.setDirectory(path);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;ui->lineEdit_2->setText(import_path);
}

        在wizardPage1页面点击下一步会跳转到下一页。这一页没什么代码,在ui文件里添加提示即可,然后点击完成按钮完成创建。在完成时我们可以重写QWidzard的done函数。
将页面设置的项目名称和路径传递给ProTree类,ProTree类用来在MainWindow左侧显示树形目录,这个之后介绍。

void Wizard::done(int result)
{if(result == QDialog::Rejected){return QWizard::done(result);}QString name, path;ui->wizardPage1->GetProSettings(name, path);emit SigProSettings(name, path);QWizard::done(result);
}

        这里面我们定义了一个GetProSettings函数去获取从lineEdit里面得到的name和path信息。然后设计一个信号把name和path信息给发出去。

void WizardPage1::GetProSettings(QString &name, QString &path)
{name = ui->lineEdit->text();path = ui->lineEdit_2->text();
}

        到此为止我们创建项目有关的内容已经基本完成,下一节我们将会去实现关于把项目文件列表在treeView里面显示出来。

相关文章:

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

经过一段时间的学习&#xff0c;相信大家对QT的基本用法都有所了解&#xff0c;从这篇文章开始&#xff0c;我准备记录一下电子相册的项目的一个学习过程。 实现项目创建功能 对于这个电子相册的项目&#xff0c;我并没有在一开始就把所有可能用到的功能模块去事无巨细的考虑周…...

机械臂与Realsense D435 相机的手眼标定ROS包

本教程主要介绍机械臂与 Realsense D435 相机手眼标定的配置及方法。 系统&#xff1a;Ubuntu 20.0.4 ◼ ROS&#xff1a;Noetic ◼ OpenCV 库&#xff1a;OpenCV 4.2.0 ◼ Realsense D435&#xff1a;librealsense sdk&#xff08;2.50.0&#xff09;、realsense-ros 功能包&…...

ubuntu使用记录——如何使用wireshark网络抓包工具进行检测速腾激光雷达的ip和端口号

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言wireshark网络抓包工具1.wireshark的安装2.wireshark的使用3.更改雷达ip 总结 前言 Wireshark是一款备受赞誉的开源网络协议分析软件&#xff0c;其功能之强大…...

C#学习指南:重要内容与实用技巧

学习C#编程是一段充满挑战但又非常充实的旅程。以下是我在学习过程中积累的一些经验&#xff0c;希望能对大家有所帮助。 一、掌握基础概念 类及其成员 C#中的类是编程的基础模块。理解类的结构、属性、方法和构造函数是至关重要的。每个类都有其特定的功能&#xff0c;学会如…...

display(a,b)什么意思

在Python中&#xff0c;如果你看到display(a,b)这样的代码&#xff0c;它通常意味着有人正在使用IPython.display模块中的display函数来同时显示两个对象。 IPython.display是Jupyter Notebook和JupyterLab等交互式计算环境的一部分&#xff0c;它提供了一种在笔记本中显示各种…...

SpringBoot3整合阿里云短信服务-1(配置阿里云短信服务)

SpringBoot3整合阿里云短信服务-1(配置阿里云短信服务) 一、开通阿里云短信服务 阿里云官网:阿里云官网 选择产品中企业服务与云通信中的短信服务 选择免费开通 选择快速学习和测试 根据这几个全部配置一下我这里是配置好了所以学习进度是100% 1.1 添加资质 首先选择新增资质 …...

基于HAL库控制LED流水灯

一. 了解并掌握HAL库函数开发方法。安装 stm32CubeMX&#xff0c;配合Keil&#xff0c;使用HAL库方式完成下列任务&#xff1a; 1、重做上一个LED流水灯作业&#xff0c;用GPIO端口完成2只LED灯的周期闪烁。 2、接上&#xff0c;再用GPIO端某一管脚接一个开关&#xff08;用杜邦…...

利用kubeadm安装k8s集群 以及跟harbor私有仓库下载镜像

目录 环境准备 master&#xff08;2C/4G&#xff09; 192.168.88.3 docker、kubeadm、kubelet、kubectl、flannel node01&#xff08;2C/2G&#xff09; 192.168.88.4 docker、kubeadm、kubelet、kubectl、flannel node02&#xff08;…...

明天(周六)下午!武汉Linux爱好者线下沙龙,我们在华中科技大学等你!

2024 年 5月 25 日&#xff08;周六&#xff09;下午&#xff0c;我们将在「武汉市洪山区」 珞喻路 1037 号华中科技大学南五楼 613 室举办武汉 Linux 爱好者线下沙龙&#xff08;WHLUG&#xff09;&#xff0c;欢迎广大 Linux 爱好者来到现场&#xff0c;与我们一同交流技术&a…...

MySQL主从复制(五):读写分离

一主多从架构主要应用场景&#xff1a;读写分离。读写分离的主要目标是分摊主库的压力。 读写分离架构 读写分离架构一 架构一结构图&#xff1a; 这种结构模式下&#xff0c;一般会把数据库的连接信息放在客户端的连接层&#xff0c;由客户端主动做负载均衡。也就是说由客户…...

阿里巴巴 EasyExcel 真正的高效与通用导入(亿级数据秒级导入)

需要lombok、hutool、alibaba EasyExcel 相关依赖包 基于Lamba表达式的通用监听器 import cn.hutool.core.util.StrUtil; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import lombok.experimental.UtilityClass…...

32.5k star!!替换 postman?【送源码】

在软件开发过程中&#xff0c;API&#xff08;应用程序接口&#xff09;扮演着至关重要的角色。为了确保 API 的可靠性和性能&#xff0c;开发人员需要一种高效的方式来测试和调试它们。这方面的工具&#xff0c;大家经常用到的应该就是 postman 了。不过&#xff0c;今天了不起…...

课时135:awk实践_逻辑控制_综合实践

1.3.8 综合实践 学习目标 这一节&#xff0c;我们从 网络实践、文件实践、小结 三个方面来学习 网络实践 简介 所谓的网络实践&#xff0c;主要是借助于awk的数组功能&#xff0c;进行站点的信息统计操作。准备网络环境 安装软件 yum install nignx -y重启nginx [rootloca…...

c++ 读取MNIST数据集实现softmax回归

pytorch教材 3.4. softmax回归 — 动手学深度学习 2.0.0 documentation c实现代码 代码太长了就没整理了&#xff0c;也暂时没有运行效果截图 同样没有本文也没有实现反向自动求导 超长代码警告&#xff0c;757行。不过可能注释占一半 #include <bits/stdc.h> usin…...

JS-04何为继承以及实现方式

目录 1 JS中继承的概念 2 为什么要使用继承&#xff1f;-解决内存浪费 2.1 问题引入 2.2 问题解决 2.3 拓展 3 继承的实现方式 3.1 原型链继承 1 3.2 原型链继承 2 1 JS中继承的概念 通过【某种方式】让一个对象可以访问到另一个对象中的属性和方法&#xff0c;我们把这种…...

6款网站登录页(附带源码)

6款网站登录页 效果图及部分源码123456 领取源码下期更新预报 效果图及部分源码 1 部分源码 <style>* {margin: 0;padding: 0;}html {height: 100%;}body {height: 100%;}.container {height: 100%;background-image: linear-gradient(to right, #fbc2eb, #a6c1ee);}.l…...

spring boot打的包直接运行

Spring Boot 提供了一个插件 spring-boot-maven-plugin 把程序打包成一个可执行的jar包&#xff0c;直接执行java -jar xxx.jar即可以启动程序 1、引用 spring-boot-maven-plugin插件 <build><plugins><plugin><groupId>org.springframework.boot<…...

移除元素-力扣

第一种解法&#xff0c;暴力解法&#xff0c;使用两个for循环一个进行遍历&#xff0c;一个进行覆盖&#xff0c;代码如下&#xff1a; class Solution { public:int removeElement(vector<int>& nums, int val) {int size nums.size();for(int i 0; i < size; …...

代码随想录算法训练营第三天| 203.移除链表元素、 707.设计链表、 206.反转链表

203.移除链表元素 题目链接&#xff1a; 203.移除链表元素 文档讲解&#xff1a;代码随想录 状态&#xff1a;没做出来&#xff0c;做题的时候定义了一个cur指针跳过了目标val遍历了一遍链表&#xff0c;实际上并没有删除该删的节点。 错误代码&#xff1a; public ListNode re…...

【题解】AB33 相差不超过k的最多数(排序 + 滑动窗口)

https://www.nowcoder.com/practice/562630ca90ac40ce89443c91060574c6?tpId308&tqId40490&ru/exam/oj 排序 滑动窗口 #include <iostream> #include <vector> #include <algorithm> using namespace std;int main() {int n, k;cin >> n &…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...