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]);
        }
    }

}

(存着自己看看)

项目原例子源码:链接

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

相关推荐
汇能感知4 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
疾风铸境4 小时前
qt+halcon开发相机拍照软件步骤
数码相机·qt·halcon·拍照
阿巴Jun4 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao5 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾5 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
抠脚学代码5 小时前
Ubuntu Qt x64平台搭建 arm64 编译套件
数据库·qt·ubuntu
DKPT6 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
ST.J6 小时前
前端笔记2025
前端·javascript·css·vue.js·笔记
Suckerbin6 小时前
LAMPSecurity: CTF5靶场渗透
笔记·安全·web安全·网络安全
眠りたいです6 小时前
基于脚手架微服务的视频点播系统-播放控制部分
c++·qt·ui·微服务·云原生·架构·播放器