QT7_视频知识点笔记_67_项目练习(页面以及对话框的切换,自定义数据类型,DB数据库类的自定义及使用)

news2024/10/5 23:29:36

视频项目:7----汽车销售管理系统(登录,品牌车管理,新车入库,销售统计图表)-----项目视频没有,代码也不全,更改项目练习:学生信息管理系统。

学生信息管理系统:简介:两个页面:主页面+学生信息添加页面(下面的例子仅举例学号和姓名)

在这里插入图片描述
在这里插入图片描述

1.点击添加按钮弹出添加对话框

添加一个继承自QDialog的QT界面类AddDialog(注意如果AddDialog是继承QWidget的话在主页面new 一个AddDialog的时候AddDialog页面会直接显示在主页面上)
主页面:

#include "adddialog.h"
...
AddDialog *m_addDialog;  //添加学生信息窗口

//构造函数:
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    m_addDialog = new AddDialog(this);
}
void Widget::on_pushButton_add_clicked()
{
    //点击按钮弹出新增窗口
    qDebug()<<"on_pushButton_add_clicked";
    
    m_addDialog->show();
}

2.添加按钮点击取消则关闭对话框

void AddDialog::on_btnCancel_clicked()
{
    qDebug()<<"on_btnCancel_clicked";
    this->close();
}

3.添加一个数据类定义需要存储数据类型(子界面存入,传递给主界面显示)

添加Q_DECLARE_METATYPE(type)宏,能使type类型让所有基于模板的函数识别

#ifndef CSTUDENTINFO_H
#define CSTUDENTINFO_H

#include <QString>
#include <QMetaType>

class CStudentInfo
{
public:
    CStudentInfo();

    bool setData(int id,QString name);

    int id() const;
    void setId(int id);

    QString name() const;
    void setName(const QString &name);

private:
    //此处举例仅用两个数据信息类
    int m_id;              //学生id 四位数字
    QString m_name;        //学生名称

};

Q_DECLARE_METATYPE(CStudentInfo)// 该宏放在类或结构体声明的最后面
#endif // CSTUDENTINFO_H

#include "cstudentinfo.h"

CStudentInfo::CStudentInfo()
{

}

bool CStudentInfo::setData(int id, QString name)
{
    m_id = id;
    m_name = name;
    return true;
}

int CStudentInfo::id() const
{
    return m_id;
}

void CStudentInfo::setId(int id)
{
    m_id = id;
}

QString CStudentInfo::name() const
{
    return m_name;
}

void CStudentInfo::setName(const QString &name)
{
    m_name = name;
}

在子界面上按这个数据类存进入:

void AddDialog::on_btnConfirm_clicked()
{
    qDebug()<<"on_btnConfirm_clicked";
	//......
    //把检测合格的数据添加进入
    int id = ui->edtId->text().toInt();
    QString name = ui->edtName->text();

    //数据类型
    CStudentInfo stuInfo;
    stuInfo.setData(id,name);

    //仅进行数据的修改到主页面,对话框不关闭
    emit sig_addStuInfo(stuInfo);
}

通过信号槽把数据类接收,并显示在主页面:
信号槽传递:

//关联槽函数
    connect(m_addDialog,&AddDialog::sig_addStuInfo,this,&Widget::slot_addStuInfo);

bool Widget::slot_addStuInfo(CStudentInfo &stuInfo)
{
    //收到添加对话框发出的信号,把添加的内容显示到UI上
    appendToModel(stuInfo);		//此处可以收到信号传来的
    return true;
}

主页面model模型显示:
构造函数中:

	//实例化model
    m_standardModel = new QStandardItemModel(this);

    //设置tableView 菜单策略 customContextMenuRequested(const QPoint &pos)
    ui->tableView_StudentInfo->setContextMenuPolicy(Qt::CustomContextMenu);

    //添加表头
    QStringList headerList;
    headerList<<"学号"<<"姓名";
    m_standardModel->setHorizontalHeaderLabels(headerList);

    ui->tableView_StudentInfo->setModel(m_standardModel);
bool Widget::appendToModel(CStudentInfo &stuInfo)
{
    QStandardItem *itemId = new QStandardItem(QString("%1").arg(stuInfo.id(),4,10,QLatin1Char('0')));
    itemId->setCheckable(true); //添加复选框
    itemId->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

    QStandardItem *itemName = new QStandardItem(stuInfo.name());
    itemName->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

    QList<QStandardItem*> rowItem;
    rowItem.append(itemId);
    rowItem.append(itemName);

    m_standardModel->appendRow(rowItem);
    return true;

}

效果:(后续需要添加学号是否存在验证等需另外再加入判断)在这里插入图片描述

4.加入数据库进行数据的长期存储,主页面显示,子页面写入,以及删除功能

先创建一个数据库的类CDataSQLite:

#ifndef CDATASQLITE_H
#define CDATASQLITE_H

#include "cstudentinfo.h"
#include <QSqlDatabase>

class CDataSQLite
{
public:
    CDataSQLite();

    /**
     * @brief 查询所有信息
     * @param stuInfos
     * @return
     */
     //用来遍历
    virtual bool selectStuInfos(QList<CStudentInfo> &stuInfoList) ;     
    //用来新增
    virtual bool addStuInfo(CStudentInfo &stuInfo) ;                    
    virtual bool updateStuInfo(CStudentInfo &stuInfo) ;
    //用来删除
    virtual bool deleteStuInfo(int id) ;                                
private:
    QSqlDatabase m_db;  //数据库连接
};

#endif // CDATASQLITE_H

CDataSQLite的构造函数:

	//打开数据库
    m_db = QSqlDatabase::addDatabase("QSQLITE"); //QMYSQL
    m_db.setDatabaseName("./stuInfoDB_demo.db"); // 相对路径是相对于.exe所在的文件夹下(即bin文件夹下)
    if(!m_db.open())
    {
        qDebug() << "Failed to Open database";
        return;
    }
    qDebug() << "success Open ";
    
    //如果没有这个表则会创建
    QSqlQuery query;
    QString sql = QString("create table if not exists tb_stuInfo"
                          "(id int primary key not null,"
                          "name varchar(50),"
                          "overallScore real);");
    if(!query.exec(sql))
    {
        qDebug() << "Failed to create table";
        qDebug() << query.lastQuery();
        return;
    }

    //关闭数据库
    m_db.close();

bool CDataSQLite::addStuInfo(CStudentInfo &stuInfo)
{
	//新增
    if(!m_db.open())
    {
        qDebug() << "Failed to Open Database : addStuInfo";
        return false;
    }
    QSqlQuery query;
    query.prepare("insert into tb_stuInfo (id,name)"
                  "values(:id,:name)");
    query.bindValue(":id",stuInfo.id());
    query.bindValue(":name",stuInfo.name());
    if(!query.exec())
    {
        qDebug() << query.lastQuery();
        m_db.close();
        return false;
    }
    m_db.close();
    return true;

}


bool CDataSQLite::selectStuInfos(QList<CStudentInfo> &stuInfoList)
{
    //查询
    if(!m_db.open())
    {
        qDebug() << "Failed to Open Database : selectStuInfos";
        return false;
    }
    QSqlQuery query;
    QString sql = "Select * from tb_stuInfo;";
    if(!query.exec(sql))
    {
        qDebug() << "Failed to selcet tb_stuInfo;";
        return false;
    }
    while(query.next())
    {
        CStudentInfo stuInfo;
        int id = query.value("id").toInt();
        QString name = query.value("name").toString();
        stuInfo.setData(id,name);
        stuInfoList.append(stuInfo);
    }
    m_db.close();
    return true;
}

bool CDataSQLite::deleteStuInfo(int id)
{
    if(!m_db.open())
    {
        qDebug() << "Failed to Open Database : deleteStuInfo";
        return false;
    }
    QSqlQuery query;
    QString sql = QString("delete from tb_stuInfo where id = %1").arg(id);
    if(!query.exec(sql))
    {
        qDebug() << "Failed to delete stuInfo!!!";
        m_db.close();
        return  false;
    }

    m_db.close();
    return true;
}

使用CDataSQLite数据库类:
在主页面中,构造函数中会先实例化数据库类,然后进行遍历查询进行显示。

//在.h文件中
CDataSQLite  *m_dataSource;  //数据源


//.cpp构造函数中
//实例化数据源
    m_dataSource = new CDataSQLite();

    //查询数据
    QList<CStudentInfo> stuInfoList;
    bool res = m_dataSource->selectStuInfos(stuInfoList);
    if(!res)
    {
        QMessageBox::information(this,"提示","查询学生信息失败");
        return;
    }
    qDebug() << stuInfoList.size();
    for(int i=0;i<stuInfoList.size();++i)
    {
        appendToModel(stuInfoList[i]);
    }

在新增页面点击确认发送信号之后,主页面接收到信号在槽函数中进行数据库类新增


//接收到子页面的确认添加按钮发出的处理信号的槽函数
bool Widget::slot_addStuInfo(CStudentInfo &stuInfo)
{
    //把数据添加到数据库中
    bool res = m_dataSource->addStuInfo(stuInfo);
    if(!res)
    {
        QMessageBox::information(this,"提示","插入失败!!!");
        return false;
    }
    //收到添加对话框发出的信号,把添加的内容添加
    appendToModel(stuInfo);
    return true;
}

删除:主页面的删除按钮点击之后槽函数:on_pushButton_delate_clicked,会把勾选的数据从数据库中以及主页面中删除


void Widget::on_pushButton_delate_clicked()
{
    QMap<int,QStandardItem*> delRowsMap;  //待删除的行
    for(int row = 0;row<m_standardModel->rowCount();++row)
    {
        QStandardItem *item = m_standardModel->item(row);
        if(item->checkState() == Qt::Checked)
        {
            delRowsMap.insert(row,item);
        }
    }

    if(delRowsMap.size()<1)
        return;

    //弹出删除提示
    int res = QMessageBox::information(this,"提示","是否真的要删除",QMessageBox::Yes|QMessageBox::No);
    if(res == QMessageBox::No) return;

    QList<int> keyList = delRowsMap.keys();
    //1.删除数据库中的数据
    for(int key=keyList.size()-1;key>=0;--key)
    {
        if(m_dataSource->deleteStuInfo(delRowsMap.value(keyList[key])->text().toInt()))
        {
            //2.删除窗口中的数据
            m_standardModel->removeRow(keyList[key]);
        }
    }

}

在这里插入图片描述
(存着自己看看)
项目原例子源码:链接
项目练习源码(跟博客相同,但是功能相比原例子不全):链接

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

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

相关文章

智能除螨—wtn6040-8s语音芯片方案引领除螨仪新时代

语音螨仪开发背景&#xff1a; 随着物联网技术的快速发展&#xff0c;除螨仪作为家庭清洁的重要工具&#xff0c;其智能化、人性化的设计成为提升市场竞争力的关键。置入语音芯片的除螨仪&#xff0c;通过开机提示、工作状态反馈、操作指引、故障提醒等内容。用户可以更加直观…

文献解读-群体基因组第二期|《中国人群中PAX2新生突变的检测及表型分析:一项单中心研究》

关键词&#xff1a;应用遗传流行病学&#xff1b;群体测序&#xff1b;群体基因组&#xff1b;基因组变异检测&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;Detection of De Novo PAX2 Variants and Phenotypes in Chinese Population: A Single-Cente…

AI智能分析技术与安防视频融合当前面临的困难与挑战

人工智能与安防视频的融合为现代安全领域带来了革命性的变化&#xff0c;提高了安全管理水平、降低了管理成本并为用户提供了更加便捷和高效的服务。随着技术的不断进步和应用场景的不断拓展&#xff0c;未来人工智能与安防的融合将展现出更加广阔的发展前景。然而&#xff0c;…

Pi 母公司将开发情感 AI 商业机器人;Meta 科学家:Sora 不是视频生成唯一方向丨RTE 开发者日报 Vol.214

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…

不用写采集规则的网页采集软件

传统的网页采集工具采集网页数据&#xff0c;需要查看和研究网页代码&#xff0c;编写复杂繁琐的采集规则&#xff0c;对于有技术基础的人&#xff0c;配置一个采集规则也要花费不少时间&#xff0c;更何况对于不懂技术的普通用户来说&#xff0c;简直是一项不太可能完成的任务…

开源表单流程设计器有哪几个突出的优势特点?

当前&#xff0c;传统的表单制作已经无法满足现在企业的发展需求了。想要实现高效率发展&#xff0c;需要引进先进的低代码技术平台、开源表单流程设计器等优秀软件平台助力发展。它们具有可视化操作界面、灵活好操作、易维护、效率高等诸多优势特点&#xff0c;在推动企业实现…

如何使用 .htaccess 删除文件扩展名

本周有一个客户&#xff0c;购买Hostease的虚拟主机&#xff0c;询问我们的在线客服&#xff0c;如何使用 .htaccess 删除文件扩展名&#xff1f;我们为用户提供相关教程&#xff0c;用户很快解决了遇到的问题。在此&#xff0c;我们分享这个操作教程&#xff0c;希望可以对您有…

Docker化Spring Boot3应用:从镜像构建到部署

随着容器化技术的发展&#xff0c;越来越多的应用采用了容器化部署的方式。容器化部署极大地减少了因部署环境不同带来的差异&#xff0c;实现了一次构建、随处运行的效果。此外&#xff0c;容器化还具有版本管理、快速启动、持续集成等优点。今天&#xff0c;我们将介绍如何在…

【linux】运维-基础知识-认知hahoop周边

1. HDFS HDFS&#xff08;Hadoop Distributed File System&#xff09;–Hadoop分布式文件存储系统 源自于Google的GFS论文&#xff0c;HDFS是GFS的克隆版 HDFS是Hadoop中数据存储和管理的基础 他是一个高容错的系统&#xff0c;能够自动解决硬件故障&#xff0c;eg&#xff1a…

解读 | 上海房地产政策松绑,售楼电话被“打爆”

图片来源千图网 自5月27日晚间上海发布房地产政策松绑消息以来&#xff0c;城市楼市气氛仿佛被一股暖流席卷&#xff0c;售楼电话几乎在一夜之间被“打爆”。这一次调整的政策涉及到多个方面&#xff0c;包括首套房首付比例的下调、二套房首付比例的调整、房贷利率的优惠等&am…

JAVA:Random详解

Java中的java.util.Random类用于生成伪随机数。它提供了多种方法来生成不同类型的随机数&#xff0c;包括整数、浮点数和布尔值。以下是对Random类及其主要方法的详细介绍 一、生成随机数 创建一个Random对象&#xff0c;可以使用以下两种方式&#xff1a; 无参构造函数&…

地图下钻,双击返回上一级

介绍&#xff1a; 看了好多地图下钻的案例&#xff0c;要么json文件不全胡&#xff0c;要么返回功能不全胡&#xff0c;有的返回是直接写死&#xff0c;返回到首页&#xff0c;我这个小案例是使用地理小工具的数据&#xff0c;本案例可以逐步一级一级的返回&#xff0c;地图的其…

中学生学人工智能系列:如何用AI学英语

经常有读者朋友给公众号《人工智能怎么学》留言咨询如何使用人工智能学习语文、数学、英语等科目。这些都是中学教师、中学生朋友及其家长们普遍关注的问题。仅仅使用留言回复的方式&#xff0c;不可能对这些问题做出具体和透彻的解答&#xff0c;因此本公众号近期将推出中学生…

用户流失分析:如何使用Python训练一个用户流失预测模型?

引言 在当今商业环境中&#xff0c;客户流失分析是至关重要的一环。随着市场竞争的加剧&#xff0c;企业需要更加注重保持现有客户&#xff0c;并深入了解他们的离开原因。本文探讨了用户流失分析的核心概念以及如何构建客户流失预测模型的案例。通过分析用户行为数据和交易模式…

网络工程基础 不同网段下的设备实现通信

交换机可以实现同一个网段下的不同设备直接通信 路由器可以实现不同的网段下的设备进行通信 路由器查看路由表命令 display ip routing-table 华为路由器配置静态路由命令&#xff1a; ip route-static 目的网络地址 子网掩码 下一跳地址 电脑判断不同网段的ip会把请求转给网…

AI - 如何科学的使用提示词

一、目的&#xff1a; 在人工智能领域&#xff0c;尤其是在与AI交互的过程中&#xff0c;精确而高效的提示词至关重要。它们不仅能够引导AI更准确地理解我们的需求&#xff0c;还能提升整个交流过程的质量和效率。解决大模型很多时候不能给出我们想要的结果的问题&#xff0c;…

任务3.1:采用面向对象方式求三角形面积

面向对象编程&#xff08;OOP&#xff09;是一种将现实世界中的实体抽象为对象&#xff0c;并通过类和对象来模拟现实世界中的行为和属性的编程范式。在本实战任务中&#xff0c;我们通过创建一个Triangle类来模拟现实世界中的三角形&#xff0c;并使用面向对象的方法来求解三角…

OrangePi AIpro 快速上手初体验——接口、样例和目标检测

​ 一、 开发板简介 OrangePi AIpro开发板是香橙派联合华为精心打造的高性能 AI 开发板&#xff0c;其搭载了昇腾 AI 处理器&#xff0c;可提供 8TOPS INT8 的计算能力&#xff0c;内存提供了 8GB 和 16GB两种版本。可以实现图像、视频等多种数据分析与推理计算&#xff0c;可…

stm32学习-CubeIDE开发

参考正点原子CubeIDE视频 stm32开发常用开发环境&#xff08;代码编写软件&#xff09; MDK5&#xff1a;通用所有的ARM芯片&#xff0c;收费、界面功能原始 CubeMxMDK5&#xff1a;CubeMX图形化配置外设&#xff0c;生成Hal库代码 CubeIDE&#xff08;集成了CubeMX&#…

C++进阶篇章:set与map(pair , multiset , multimap)

目录 1.关联式容器与序列式容器 2.pair&#xff08;键值对&#xff09; 3.set 构造函数 find函数 count函数&#xff1a; insert函数 4.multiset 5.map insert函数 operator[] 1.关联式容器与序列式容器 C中关联式容器与序列式容器是两种不同的容器 1.关联式容器 关…