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

news2024/12/27 13:48:21

        经过一段时间的学习,相信大家对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里面显示出来。

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

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

相关文章

mysql数据库主从复制,搭建从库

1 期望效果 假设我们现在有两个服务器&#xff0c;两个服务器都有数据库&#xff0c;然后我们命名一个叫主数据库&#xff08;Master&#xff09;&#xff0c;一个叫从数据库&#xff08;Slave&#xff09; 数据备份和容灾&#xff1a;通过主从复制&#xff0c;可以将主数据库…

【运维心得】双WAN配置的一个误区

目录 双WAN配置及优势 实际案例 解决之道 最后总结 双WAN配置及优势 什么是双WAN配置&#xff0c;这里就不多赘述&#xff0c;简单的说&#xff0c;首先你要有一台支持双WAN口的路由器&#xff0c;目前大多数企业级路由器都具备了这个功能。甚至有些家用路由器也有此类功能…

.gitignore配置以及解决文件不生效

.gitignore配置 新建.gitignore文件 文件内容如下&#xff1a; ###################################################################### # Build Tools.gradle /build/ !gradle/wrapper/gradle-wrapper.jarnbsdk/ logs/target/ !.mvn/wrapper/maven-wrapper.jar##########…

notepad++ 批量转所有文件编码格式为UTF-8

1、安装notepad及PythonScript_3.0.18.0插件 建议两者都保持默认路径安装x64版本&#xff1a; 阿里云盘分享https://www.alipan.com/s/xVUDpY8v5QL安装好后如下图&#xff1a; 2、new Script&#xff0c;新建脚本&#xff0c;文件名为ConvertEncoding 3、自动打开脚本&#xff…

Acrobat Pro DC 2024 Mac软件安装包下载PDF2024 Mac安装教程

安装 步骤 1&#xff0c;双击打开下载好的安装包。 2&#xff0c;选择acrobat dc installer.pkg双击启动安装程序。 3&#xff0c;点击继续。 4&#xff0c;点击继续。 5&#xff0c;点击继续。 6&#xff0c;点击安装。 7&#xff0c;输入电脑密码。 8&#xff0c;软件安装中…

Web Speech API(1)—— SpeechRecognition

Web Speech API 使你能够将语音数据合并到 Web 应用程序中。Web Speech API 有两个部分&#xff1a;SpeechSynthesis 语音合成&#xff08;文本到语音 TTS&#xff09;和 SpeechRecognition 语音识别&#xff08;异步语音识别&#xff09;。 SpeechRecognition 语音识别通过 S…

由于找不到mfc140u.dll,无法继续执行代码如何解决

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是电脑找不到mfc140u.dll文件。这个问题可能会导致程序无法正常运行或系统崩溃。为了解决这个问题&#xff0c;本文将介绍5种修复方法&#xff0c;帮助大家快速恢复电脑的正常运行。 一&#x…

SD-WAN EVPN基本原理

SD-WAN EVPN是一种用于Overlay业务网络和底层传输网络分离以及业务网络路由和传输网络路由分离的VPN技术。SD-WAN EVPN技术采用类似于BGP/MPLS IP VPN的机制&#xff0c;通过扩展BGP协议&#xff0c;使用扩展后的可达性信息&#xff0c;使不同站点的底层传输网络互通&#xff0…

rocketmq 学习二 基本概念

教程&#xff1a;基本概念 | RocketMQ 视频教程 https://www.bilibili.com/video/BV1d5411y7UW?vd_sourcef1bd3b5218c30adf0a002c8c937e0a27 版本&#xff1a;5.0 一 基本概念 1.1 生产者/Producer 1.1.1 定义 消息发布者。是构建并传输消息到服务端的运行实体。…

php之web开发

目标 实现一款具有常用大部分功能的WEB应用&#xff0c;并初步了解WEB漏洞原理 登录功能&#xff1a; 1、基于前端的登录功能 <!DOCTYPE html> <html> <head> <title>简单登录功能</title> </head> <meta charset"UTF-8"…

yaml文件格式详解 及 k8s实战演示

目录 一 k8s 支持的语言格式 1&#xff0c;YAML 语法格式 2&#xff0c;查看 api 资源版本标签 二 k8s 运行nginx pod实例 yaml文件 具体讲解 1&#xff0c;写一个yaml文件demo 2&#xff0c;deployment 管理nginx 的yaml 文件 3&#xff0c;创建资源对象 4&#…

BGP(一)边界网关协议

BGP协议基础 路由分类 直连路由 非直连路由&#xff08;间接路由&#xff09; 静态路由动态路由 IGP&#xff1a;内网网关路由协议&#xff08;在企业内部或数据中心内部使用&#xff09; DV&#xff1a;距离矢量路由协议RIP&#xff08;v1/v2&#xff09;IGRP——网络直径&…

【超全干货】一文讲清什么是全民分销?怎么做好全民分销?

一、什么是全民分销&#xff1f; 全民分销&#xff0c;作为新时代营销模式的代表之一&#xff0c;是基于互联网尤其是社交媒体平台兴起的一种分销策略。它打破了传统零售与电子商务的界限&#xff0c;允许任何个人&#xff0c;无论是否为专业销售人员&#xff0c;都能成为品牌…

JJJ:ubuntu修改静态ip

一、IP变化的原因 1.DHCP协议 虚拟机系统(Ubuntu、CentOS、UOS等Linux系统)启动后&#xff0c;加入本地局域网网络时&#xff0c;会向本地网络申请租约一个IP地址&#xff0c;租约时长不定。我这里租约时间短到只有1小时左右就更换一次IP地址。 二、解决方法&#xff1a;手动…

英语学习笔记20——Look at them!

Look at them! 看看他们&#xff01; 词汇 Vocabulary big a. 大的&#xff08;尺寸&#xff0c;年龄&#xff0c;音量……&#xff09; 搭配&#xff1a;big cheese 大人物    big mouth 大嘴巴&#xff08;传话的人&#xff09;    big talker 吹牛的人 例句&#xf…

(六)Spring教程——Spring IoC容器(中)

(一)Spring教程——Spring框架简介 (二)Spring教程——Spring框架特点 (三)Spring教程——依赖注入与控制反转 (四)Spring教程——控制反转或依赖注入与Java的反射技术 (五)Spring教程——Spring IoC容器&#xff08;上&#xff09; (六)Spring教程——Spring IoC容器(中) (七)…

Milvus的执行引擎Knowhere

前言 本文将会介绍Knowhere这个概念&#xff0c;它是milvus向量执行引擎的核心。 概览 Knowhere是milvus向量咨询引擎的核心&#xff0c;它将好几个向量相似搜索库聚集在一起&#xff08;包括faiss、hnswlib、annoy&#xff09;。Knowhere也被设计支持异构计算。它控制在什么…

如何使用WindowsSpyBlocker防止Windows系统被恶意监控和跟踪

关于WindowsSpyBlocker WindowsSpyBlocker是一款功能强大的Windows系统安全防护工具&#xff0c;该工具基于Go语言开发&#xff0c;WindowsSpyBlocker以一个单独的可执行程序发布&#xff0c;可以帮助广大用户防止自己的Windows系统被恶意监控和跟踪。 WindowsSpyBlocker能够利…

使用 LlamaParse 进行 PDF 解析并创建知识图谱

此 Python 笔记本提供了有关利用 LlamaParse 从 PDF 文档中提取信息并随后将提取的内容存储到 Neo4j 图形数据库中的综合指南。本教程在设计时考虑到了实用性&#xff0c;适合对文档处理、信息提取和图形数据库技术感兴趣的开发人员、数据科学家和技术爱好者。 该笔记本电脑的主…

人工智能是“数字鹦鹉”还是有了自我意识?

相关说明 这篇文章涉及到的书籍是《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 部分章节内容可以参考&#xff1a; 理解大语言模型&#xff08;二&#xff09;——从零开始实现GPT-2利用神经网络学习语言&#xff08;四&…