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

}

(存着自己看看)

项目原例子源码:链接

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

相关推荐
今天只学一颗糖37 分钟前
Linux学习笔记--GPIO子系统和PinCtrl子系统
linux·笔记·学习
lingggggaaaa1 小时前
小迪安全v2023学习笔记(一百三十四讲)—— Windows权限提升篇&数据库篇&MySQL&MSSQL&Oracle&自动化项目
java·数据库·windows·笔记·学习·安全·网络安全
StarPrayers.2 小时前
损失函数(Loss Function)、反向传播(Backward Propagation)和优化器(Optimizer)学习笔记
人工智能·笔记·深度学习·学习
江公望3 小时前
Qt的QT_QPA_EGLFS_INTEGRATION环境变量浅解
linux·qt·qml
明月5663 小时前
github开源笔记应用程序项目推荐-Joplin
笔记·开源·joplin·跨平台笔记应用
YuCaiH4 小时前
网络编程的基础知识
linux·笔记·嵌入式·网络通信
m0_689618284 小时前
突破亚微米光电子器件制造瓶颈!配体交换辅助打印技术实现全打印红外探测器
笔记·制造
精英的英5 小时前
【工具开发】适用于交叉编译环境的QT qmake项目转换vscode项目插件
人工智能·vscode·qt·开源软件
Source.Liu5 小时前
【BuildFlow & 筑流】品牌命名与项目定位说明
c++·qt·rust·markdown·librecad
unicrom_深圳市由你创科技5 小时前
工业上位机,用Python+Qt还是C#+WPF?
python·qt·c#