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

视频项目: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]);
        }
    }

}

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

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值