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

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

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


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

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

主页面:

cpp 复制代码
#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.添加按钮点击取消则关闭对话框

cpp 复制代码
void AddDialog::on_btnCancel_clicked()
{
    qDebug()<<"on_btnCancel_clicked";
    this->close();
}

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

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

cpp 复制代码
#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
cpp 复制代码
#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;
}

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

cpp 复制代码
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);
}

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

信号槽传递:

cpp 复制代码
//关联槽函数
    connect(m_addDialog,&AddDialog::sig_addStuInfo,this,&Widget::slot_addStuInfo);

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

主页面model模型显示:

构造函数中:

cpp 复制代码
	//实例化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);
cpp 复制代码
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:

cpp 复制代码
#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的构造函数:

cpp 复制代码
	//打开数据库
    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();
cpp 复制代码
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数据库类:

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

cpp 复制代码
//在.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]);
    }

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

cpp 复制代码
//接收到子页面的确认添加按钮发出的处理信号的槽函数
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,会把勾选的数据从数据库中以及主页面中删除

cpp 复制代码
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]);
        }
    }

}

(存着自己看看)

项目原例子源码:链接

项目练习源码(跟博客相同,但是功能相比原例子不全):链接

相关推荐
codists5 分钟前
《计算机组成及汇编语言原理》阅读笔记:p82-p85
笔记
ladymorgana9 分钟前
【运维笔记】windows 11 中提示:无法成功完成操作,因为文件包含病毒或潜在的垃圾软件。
运维·windows·笔记
oneouto27 分钟前
selenium学习笔记(一)
笔记·学习·selenium
oneouto3 小时前
selenium学习笔记(二)
笔记·学习·selenium
sealaugh323 小时前
aws(学习笔记第十九课) 使用ECS和Fargate进行容器开发
笔记·学习·aws
LuH11244 小时前
【论文阅读笔记】Scalable, Detailed and Mask-Free Universal Photometric Stereo
论文阅读·笔记
矛取矛求6 小时前
QT的前景与互联网岗位发展
开发语言·qt
Leventure_轩先生6 小时前
[WASAPI]从Qt MultipleMedia来看WASAPI
开发语言·qt
m0_748256786 小时前
WebGIS实战开源项目:智慧机场三维可视化(学习笔记)
笔记·学习·开源
红色的山茶花6 小时前
YOLOv9-0.1部分代码阅读笔记-loss.py
笔记