目录
第一章 UI界面设计与开发
登录界面
主界面
UI美化
第二章 数据库设计与开发
数据库设计
连接数据库
数据库功能设计
sql语句设计
查询所有学生数量
查询第几页学生数据
删除学生
修改学生信息
清空学生表
添加单个用户
删除单个用户
修改用户权限
查询所有用户
查询用户是否存在
数据库函数设计
sql函数设计
学生表操作
Init()
getStuCnt()
getPageStu()
addStu()
delStu()
updateInfo()
clearStuInfo()
用户表操作
addUser()
delUser()
UpdateUserAut()
getAllUser()
isExists()
模拟数据
创建单例
增
删
查询
修改
清空学生表
优化
打包
样式打包
数据库打包
第一章 UI界面设计与开发
登录界面
第一步先做登录界面
新建一个文件,命名为Page_login.
在MainWindows.h头文件里声明一个Page_login类型的变量m_dlgloin:
先放置控件:
设置控件属性
然后我们将用户名输入和密码输入框设置成为默认显示:
将密码输入框的模式改为密码模式:
将用户名和密码输入长度限制为8位:
在MainWindows.cpp文件里调用我们我们m_dlogin窗口,并且把主窗口阻塞不显示:
初步登录界面如下:
右击按钮选择转到槽:会自动生成框架:
我们接下来登录和退出的逻辑
退出
exit(0);
登录
登录一般是在数据库查找用户名和密码,查找到了就发送一个signal显示成功了:
如果失败就提示登录失败.
在Mainwindows.cpp里写下面这段代码,表示如果主界面捕获到来自登录界面登录成功的信号,那么就跳到主界面:
主界面
主界面放置如下控件:效果图如下:
改变一下背景色
往treewidget里添加信息
需要用到的函数:
所以我们需要new一个 QTreeWidgetItem 类型对象. QTreeWidgetItem 的构造函数如下:第一个参数要为自身,第二个参数想用字符串的话只能构造一个qstringlist类型的参数
效果图:
让文字居左显示(把indentation设为小一点):
构造两个子集目录:学生管理,管理员管理
效果图如下:
数据模拟
把我们之前的stackwidget设置一个背景色,然后在stackwidget里加一个tablewidget控件,给tablewidget加几列数据,效果图如下:
UI美化
在Mainwindows.cpp里面的Widget类里面有一个keyPressEvent()键盘响应事件函数,它的声明如下:
virtual void keyPressEvent(QKeyEvent *event);
我们在Mainwindows.h文件里进行声明,然后在Mainwindows.cpp文件进行定义.定义如下:
我们通过f6键进行换肤,首先提前新建一个stucss.css文件,在里面我们要换的样式写好,然后在我们按完F6之后将其加载进我们的UI界面
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(event->key()==Qt::Key_F6)
{
QFile f;
auto str=QCoreApplication::applicationDirPath(); //获取application的路径
f.setFileName(str+"//"+"stucss.css"); //将路径后加上我们皮肤的路径
f.open(QIODevice::ReadOnly); //以只读方式打开
QString str2=f.readAll(); //读取
this->setStyleSheet(str2); //设置样式
m_dlgloion.setStyleSheet(str2);//采用样式
}
}
stucss.css代码如下:
/* 登录界面 */
QPushButton{color:white;background-color:#34495e;border-radius:6;} /*按钮*/
QLabel{color:#34495e;} /*标签*/
QLabel#lb1{color:#34495e;font-size: 22;} /*用户名标签*/
QLabel#lb2{color:#34495e;font-size: 22;} /*密码标签*/
QLineEdit{border: 2px solid #bdc3c7; min-height:22; border-radius: 6px;}/*搜索框 */
/* 主界面 */
/* Widget#background-color:#34495e; */
QLabel[lab="main"]{color:white;}
QWidget#widget[bg_title="main"]{background-color:#34495e;}
QWidget#widget_3{background-color:#34495e;}
QPushButton[btn="main"]{font-family:"微软雅黑";min-height:22px;min-width:80px;background-color: #16a085;border-radius:6; } /*主界面按钮*/
QPushButton[btn="main"]:pressed{font-family:"微软雅黑";min-height:22px;min-width:80px;background-color: #2a5d53;border-radius:6; } /*按钮按压变色*/
/*左侧界面样式*/
QTreeWidget{font-family:"宋体";font-size:15px;background-color: rgba(52, 73, 94, 150); color:white;}
QStackedWidget{border:1px solid gray;} 边框
/*右侧界面样式*/
QHeaderView::section
{
font-size:16px;
font-family: "宋体";
text-align:center;
height:30px;
color:#909399;
font-weight: bold;
border:1px solid gray;
border-left:none;
/* border-bottom-color: rgb(168, 171, 180); */
}
QTableWidget::item
{
font:14px "微软雅黑";
color:#667483;
border:none;
}
优化完之后的效果如下所示:
第二章 数据库设计与开发
数据库设计
新建两张表,sql语句如下:
学生表
CREATE TABLE "student" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT,
"age" integer,
"grade" integer,
"class" integer,
"studentid " integer,
"phone" TEXT,
"wechat" TEXT
);
用户表
CREATE TABLE "username" (
"username" TEXT,
"password" TEXT,
"auth" TEXT
);
此时数据库里就有两张表了
创建一个新的基于OBject类的头文件,命名为stusql.cpp
在这个文件进行数据库操作
连接数据库
连接数据库的模板如下:
#include "stusql.h"
#include <QMessageBox>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
stusql::stusql(QObject *parent )
: QObject {parent}
{
// 检查是否有可用的数据库驱动
if (QSqlDatabase::drivers().isEmpty()) {
// 确保 stusql 类是 QObject 的子类,否则需要传递一个有效的 QWidget 指针或 nullptr
QMessageBox::information(nullptr, tr("No database drivers found"),
tr("This demo requires at least one Qt database driver. "
"Please check the documentation how to build the "
"Qt SQL plugins."));
return;
}
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); // 创建一个数据库连接
db.setDatabaseName("./data.db");
if (!db.open()) {
qDebug() << "数据库文件加载失败: " << db.lastError().text();
// 这里可能需要处理错误,比如显示一个消息框或者记录日志
return; // 数据库打开失败,构造函数不应该继续执行
}
qDebug() << "打开数据库文件成功";
此时构建完之后控制台显示
然后我们可以向数据库里插一条数据看一下是否可以插入成功:
语句如下:
QSqlQuery q("", db);
if (!q.exec("INSERT INTO student VALUES (NULL ,'张三',12,3,2,1,15518978071,'aasDASD')")) {
qDebug() << "插入数据失败: " << q.lastError().text();
// 这里应该处理SQL执行错误
}
此时构建完之后控制台显示:
我们现在可以让插入失败的原因可视化的显示出来:
if (!q.exec("INSERT INTO student VALUES (NULL ,'张三',12,3,2,1,15518978071,'aasDASD')")) {
QMessageBox::critical(nullptr, tr("Database Error"),
tr("Failed to insert data: %1").arg(q.lastError().text()));
// 显示具体的错误信息
}
这样的话就会有一个断言:显示表不存在
我把路径换成绝对路径就可以了:
db.setDatabaseName("D:\\QTproject\\stumanger\\data.db");
现在数据库里student表就被插入一条数据了:
数据库功能设计
sql语句设计
查询所有学生数量
select count(id) from student;
查询第几页学生数据
offset代表从第几条记录之后"开始"查询,limit表示查询多少条结果
select * from student order by id limit 2 offset 1;
删除学生
delete from student where id = 1;
修改学生信息
update student set name = 'asd' where id=25;
清空学生表
delete from student
添加单个用户
INSERT INTO "username" VALUES ('admin', 111, 'admin');
删除单个用户
delete from username where username='admin';
修改用户权限
update username set auth='user';
查询所有用户
select * from username
查询用户是否存在
select *from username where username='admin';
数据库函数设计
实现基础的数据库增删查改功能,在stusql.h文件里列出以下声明:
首先创建两个结构体
在stusql.cpp文件里实现定义:
sql函数设计
学生表操作
Init()
在初始化的时候进行数据库连接
void stusql::Init()
{
m_db = QSqlDatabase::addDatabase("QSQLITE"); // 创建一个数据库连接
m_db.setDatabaseName("D:\\QTproject\\stumanger\\data.db");
#if 0
auto str=QCoreApplication::applicationDirPath(); //获取一下数据库的路径,目的是为了发布时找到数据库将其放于当前目录下
qDebug()<<str;
#endif
if (!m_db.open()) {
QMessageBox::critical(nullptr, tr("Database Error"),
tr("Failed to open database: %1").arg(m_db.lastError().text()));
return; // 数据库打开失败,构造函数不应该继续执行
}
qDebug() << "打开数据库文件成功";
}
getStuCnt()
quint32 stusql::getStuCnt()
{
QSqlQuery sql(m_db);
sql.exec("select count(id) from student;");
quint32 Cnt=0;
while(sql.next())
{
Cnt=sql.value(0).toUInt();
}
qDebug() << "学生数量: " << Cnt;
return Cnt;
}
getPageStu()
QList<StuInfo> stusql::getPageStu(quint32 page, quint32 Cnt)
{
QList<StuInfo> l;
QSqlQuery sql(m_db);
QString strsql=QString("select * from student order by id limit %1 offset %2;")
.arg(Cnt)
.arg(page*Cnt);
sql.exec(strsql);
StuInfo info;
while(sql.next())
{
info.id=sql.value(0).toUInt();
info.stu_name=sql.value(1).toString();
info.stu_age=sql.value(2).toUInt();
info.stu_grade=sql.value(3).toUInt();
info.stu_class=sql.value(4).toUInt();
info.stu_id=sql.value(5).toUInt();
info.stu_phone=sql.value(6).toString();
info.stu_wechat=sql.value(7).toString();
}
l.push_back(info);
// qDebug()<<l.begin()->id<<l.begin()->stu_name<<l.begin()->stu_age;
return l;
}
addStu()
添加记录
bool stusql::addstu(StuInfo info)
{
QSqlQuery sql(m_db);
QString strsql=QString("insert into stdent values(null,'%1',%2,%3,%4,%5,'%6','%7')")
.arg(info.stu_name)
.arg(info.stu_age)
.arg(info.stu_grade)
.arg(info.stu_class)
.arg(info.stu_id)
.arg(info.stu_phone)
.arg(info.stu_wechat);
if(!sql.exec(strsql))
{
QMessageBox::critical(nullptr, tr("Database Error"),
tr("Failed to insert data: %1").arg(sql.lastError().text()));
// 显示具体的错误信息
return false;
}
return true;
}
delStu()
bool stusql::delStu(int id)
{
QSqlQuery sql(m_db);
QString strsql=QString("delete from student where id= %1;")
.arg(id);
if(sql.exec(strsql))
{
return true;
}
else qDebug()<<"删除失败!";
return false;
}
updateInfo()
修改学生信息
bool stusql::updateInfo(StuInfo info)
{
QSqlQuery sql(m_db);
QString strsql=QString("update student set name = '%1' where id=%2;")
.arg(info.stu_name)
.arg(info.stu_id);
bool res=sql.exec(strsql);
QSqlError e=sql.lastError();
if(sql.isValid())
{
qDebug()<<e.text();
}
return res;
}
发现怎么修改都无法修改,后来发现是建表的问题(字段名后面有空格)
clearStuInfo()
清空学生表
void stusql::clearStuInfo()
{
QSqlQuery sql(m_db);
QString strsql=QString("delete from student");
sql.exec(strsql);
}
在表设计视图里面把这些空格删掉就可以了
用户表操作
addUser()
//添加单个用户
bool stusql::addUser(UserInfo info)
{
QSqlQuery sql(m_db);
QString strsql = QString("INSERT INTO username VALUES ('%1', '%2', '%3');")
.arg(info.username)
.arg(info.passwd)
.arg(info.auth);
if(!sql.exec(strsql))
{
qDebug()<<"ERROR:"<<sql.lastError();
return false;
}
return true;
}
delUser()
bool stusql::delUser(QString userName)
{
QSqlQuery sql(m_db);
QString strsql =QString("delete from username where username= '%1'").arg(userName);
if(!sql.exec(strsql))
{
qDebug()<<"ERROR:"<<sql.lastError();
return false;
}
return true;
}
UpdateUserAut()
bool stusql::UpdateUserAut(QString str1, QString str2)
{
QSqlQuery sql(m_db);
// 使用参数化查询来避免SQL注入
QString strsql = "UPDATE username SET auth = :auth WHERE username = :username;";
// 绑定参数
sql.prepare(strsql);
sql.bindValue(":auth", str1);
sql.bindValue(":username", str2);
if (!sql.exec()) {
qDebug() << "ERROR:" << sql.lastError();
return false;
}
// 检查是否有行被更新
if (sql.numRowsAffected() > 0) {
return true;
} else {
// 没有行被更新,可能是没有找到匹配的用户名
qDebug() << "No rows updated. User may not exist.";
return false;
}
}
getAllUser()
QList<UserInfo> stusql::getAllUser()
{
QList<UserInfo> l; // 使用正确的类型
QSqlQuery sql(m_db);
QString strsql = "select * from username"; // 假设表名正确
// 执行SQL查询
if (!sql.exec(strsql)) {
// 处理错误,例如打印错误信息
qDebug() << "Error executing query:" << sql.lastError();
return l; // 返回空列表或根据需要进行错误处理
}
UserInfo info; // 在循环内部初始化
while (sql.next()) {
info.username = sql.value("username").toString(); // 假设列名为 "username"
info.passwd = sql.value("passwd").toString(); // 假设列名为 "passwd"
info.auth = sql.value("auth").toString(); // 假设列名为 "auth"
l.push_back(info); // 在每次迭代中将info添加到列表
info = UserInfo(); // 重置info对象(如果UserInfo有默认构造函数)
}
auto a=l.front();
qDebug()<<a.username<<a.passwd<<a.auth;
return l;
}
isExists()
bool stusql::isExists(QString Name)
{
QSqlQuery sql(m_db);
// 使用参数化查询来避免SQL注入,并且只查询需要的列
QString strsql = "SELECT COUNT(*) FROM username WHERE username = :name;";
// 绑定参数
sql.prepare(strsql);
sql.bindValue(":name", Name);
if (!sql.exec()) {
qDebug() << "ERROR:" << sql.lastError();
return false;
}
// 检查是否有结果返回
if (sql.next()) {
// 检查COUNT(*)是否大于0
if(sql.value(0).toLongLong() > 0)
qDebug()<<"用户存在";
else qDebug()<<"用户不存在";
}
return false;
}
造一行数据,我们发现左边会有一个自增id:我们可以通过取消一个属性将其去掉:
模拟数据
创建单例
创建单例的目的:
单例模式是qt开发的一种模式.在发布的时候有两种模式,一种是怎么把资源载入exe文件当中,还有一种就是在发布的时候引入外部资源,这种模式占用内容特别少,就是单例模式.
我们在stusql.h文件里添加单利模式的声明
static stusql *ptrstuSql;
static stusql *getinstance()
{
if(ptrstuSql==nullptr)
{
ptrstuSql=new stusql;
}
return ptrstuSql;
}
在stusql.cpp文件里面添加对单例的定义:
stusql *stusql::ptrstuSql=nullptr;
我们创建一个QStringList类型对象mlNames,然后将1000个名字读入到mlNames里面.
然后我们在主界面添加一个按钮命名为btn_moni,然后添加定义,定义如下:
void MainWindow::on_btn_moni_clicked()
{
QString l;
//制作1000条学生数据
QRandomGenerator g,c;
g.seed(0);
c.seed(0);
for(int i=0;i<mlNames.size();i++)
{
auto rand_grade=g.bounded(7,10);
auto rand_class=g.bounded(1,10);
StuInfo info;
info.stu_name=mlNames[i];
if(i%3)
{
info.stu_age=14;
}
if(i%7)
{
info.stu_age=13;
}
if(i%9)
{
info.stu_age=18;
}
info.stu_grade=rand_grade;
info.stu_class=rand_class;
info.id=i;
info.stu_phone="13463464347";
info.stu_wechat="sfwegewg";
m_ptrStusql->addstu(info);
}
}
此时我们的数据库里就有了我们模拟的数据了:
接下来我们需要将这些数据展现在我们的Qtablewidget上.
我们写一个Update()函数,内容如下:
//刷新数据
void MainWindow::updateTable()
{
//把自带的表头删了,我们自己来写表头
ui->tableWidget_2->clear();
//必须要告诉编译器有多少列才能显示表头
ui->tableWidget_2->setColumnCount(8);
QStringList l;
//自定义表头
l<<"序号"<<"姓名"<<"年龄"<<"年纪"<<"班级"<<"学号"<<"电话"<<"微信";
ui->tableWidget_2->setHorizontalHeaderLabels(l); //设置显示表头
ui->tableWidget_2->setSelectionBehavior(QAbstractItemView::SelectRows); //当用户点击任何一个单元格时,整个行都会被选中
//显示数据内容
auto cnt=m_ptrStusql->getStuCnt(); //获取记录行数
ui->lb_cnt->setText(QString("数量:%1").arg(cnt)); //显示学生数量
QList<StuInfo> lStudents=m_ptrStusql->getPageStu(0,cnt); //获取一共有多少页数据
ui->tableWidget_2->setRowCount(cnt); //设置行数
//将数据刷新到tablewidget上
for(int i=0;i<lStudents.size();i++)
{
ui->tableWidget_2->setItem(i,0,new QTableWidgetItem(QString::number(i)));
ui->tableWidget_2->setItem(i,1,new QTableWidgetItem(lStudents[i].stu_name));
ui->tableWidget_2->setItem(i,2,new QTableWidgetItem(QString::number(lStudents[i].stu_age)));
ui->tableWidget_2->setItem(i,3,new QTableWidgetItem(QString::number(lStudents[i].stu_grade)));
ui->tableWidget_2->setItem(i,4,new QTableWidgetItem(QString::number(lStudents[i].stu_class)));
ui->tableWidget_2->setItem(i,5,new QTableWidgetItem(QString::number(lStudents[i].stu_id)));
ui->tableWidget_2->setItem(i,6,new QTableWidgetItem(lStudents[i].stu_phone));
ui->tableWidget_2->setItem(i,7,new QTableWidgetItem(lStudents[i].stu_wechat));
}
}
此时我们的数据就刷新出来了:
增
接下来我们实现这几个按钮的功能:
先来实现增加按钮的功能.创建一个dlg_addstu文件,dlg_addstu.ui如下:
然后我们还有个修改操作,就不单独设计UI界面,直接用dlg_addstu.ui的界面.
我们用一个全局变量m_isAdd,如果m_isAdd为True表示当前是添加操作,为false表示当前是修改操作.
dlg_addstu.ui界面的保存按钮和取消按钮定义如下:
增加操作是我们获取一下每个输入框输入的内容,把这些信息全部传给变量info,然后再把Info作为参数传给addStu()函数执行insert SQL语句.
//保存
void Dlg_AddStu::on_btn_save_clicked()
{
StuInfo info; //把所有的字段读取到info里
auto ptr=stusql::getinstance();
info.id=m_info.id; //传id
info.stu_name=ui->le_name->text();
info.stu_age=ui->sb_age->text().toInt();
info.stu_grade=ui->le_grade->text().toInt();
info.stu_class=ui->le_class->text().toInt();
info.stu_id=ui->le_id->text().toUInt();
info.stu_phone=ui->le_phone->text();
info.stu_wechat=ui->le_wechat->text();
if(m_isAdd) //为true表示当前是添加操作
{
ptr->addstu(info);
}
else
{ //为false表示当前是修改操作
ptr->updateInfo(info);
}
QMessageBox::information(nullptr,"消息","添加成功");
this->hide(); //点击保存之后窗口消失
}
void Dlg_AddStu::setType(bool isAdd,StuInfo info)
{
m_isAdd=isAdd;
m_info=info; //把info的所有信息都给中间变量m_info,包括id
ui->le_name->setText(info.stu_name);
ui->sb_age->setValue(info.stu_age);
ui->le_grade->setText(QString::number(info.stu_grade));
ui->le_class->setText(QString::number(info.stu_class));
ui->le_phone->setText(QString(info.stu_phone));
ui->le_wechat->setText(QString(info.stu_wechat));
}
取消按钮
//取消
void Dlg_AddStu::on_btn_cancel_clicked()
{
this->hide();
}
添加按钮(调出添加输入框)
//点击添加按钮弹出添加界面
void MainWindow::on_btn_add_clicked()
{
m_dlgAddstu.setType(true); //表示true代表当前是添加操作,false代表当前是修改操作
m_dlgAddstu.exec(); //模态对话框 当前界面不操作完不能操作其他界面
// m_dlgAddstu.show(); //非模态对话框
updateTable(); //添加完成之后刷新一下界面
}
删
//删除按钮的定义如下
void MainWindow::on_btn_del_clicked()
{
int i=ui->tableWidget_2->currentRow(); //获取一下鼠标点击的记录(即需要删除的记录)
if(i>=0) //如果要删除的记录是合法记录 (即不是不存在的记录),那么就进行删除
{
int id=ui->tableWidget_2->item(i,1)->text().toUInt(); //删除需要通过id删除,这里获取id
m_ptrStusql->delStu(id); //传给我们定义的delStu()函数执行删除sql语句
updateTable(); //删除完之后刷新一下界面
QMessageBox::information(nullptr,"信息","删除成功");
}
}
查询
//搜索
void MainWindow::on_btn_seacher_clicked()
{
QString SearchFile=ui->lb_search->text(); //获取搜索输入框输入的内容
//如果输入框的内容为空就退出查询
if(SearchFile.isEmpty())
{
QMessageBox::information(nullptr,"信息","查询为空!");
updateTable();
return;
}
//必须要告诉编译器有多少列才能显示表头
ui->tableWidget_2->clear();
ui->tableWidget_2->setColumnCount(9);
QStringList l;
//自定义表头
l<<"序号"<<"id"<<"姓名"<<"年龄"<<"年纪"<<"班级"<<"学号"<<"电话"<<"微信";
ui->tableWidget_2->setHorizontalHeaderLabels(l); //设置显示表头
ui->tableWidget_2->setSelectionBehavior(QAbstractItemView::SelectRows); //当用户点击任何一个单元格时,整个行都会被选中
//显示数据内容
auto cnt=m_ptrStusql->getStuCnt(); //获取记录行数
ui->lb_cnt->setText(QString("数量:%1").arg(cnt)); //显示学生数量
ui->tableWidget_2->setSelectionBehavior(QAbstractItemView::SelectRows);//单击选中一行
ui->tableWidget_2->setEditTriggers(QAbstractItemView::NoEditTriggers);//使记录不可被直接编辑
QList<StuInfo> lStudents=m_ptrStusql->getPageStu(0,cnt); //获取一共有多少页数据
int index=0;
//将数据刷新到tablewidget上
for(int i=0;i<lStudents.size();i++)
{
//如果查询不到这个人就不执行下面的操作
if(!lStudents[i].stu_name.contains(SearchFile))
{
continue;
}
index++;
ui->tableWidget_2->setItem(i,0,new QTableWidgetItem(QString::number(index)));
ui->tableWidget_2->setItem(i,1,new QTableWidgetItem(QString::number(lStudents[i].id)));
ui->tableWidget_2->setItem(i,2,new QTableWidgetItem(lStudents[i].stu_name));
ui->tableWidget_2->setItem(i,3,new QTableWidgetItem(QString::number(lStudents[i].stu_age)));
ui->tableWidget_2->setItem(i,4,new QTableWidgetItem(QString::number(lStudents[i].stu_grade)));
ui->tableWidget_2->setItem(i,5,new QTableWidgetItem(QString::number(lStudents[i].stu_class)));
ui->tableWidget_2->setItem(i,6,new QTableWidgetItem(QString::number(lStudents[i].stu_id)));
ui->tableWidget_2->setItem(i,7,new QTableWidgetItem(lStudents[i].stu_phone));
ui->tableWidget_2->setItem(i,8,new QTableWidgetItem(lStudents[i].stu_wechat));
}
//最后统计一下查询出来的人数
ui->tableWidget_2->setRowCount(index); //设置行数
}
修改
//修改按钮
void MainWindow::on_btn_modify_clicked()
{
StuInfo info; //把当前鼠标点击的记录的每个字段添加到info里
int i=ui->tableWidget_2->currentRow(); //获取鼠标点击的行(即要修改的记录)
if(i>=0)
{
info.id=ui->tableWidget_2->item(i,1)->text().toUInt(); //获取id的值并保存在Info里
info.stu_name=ui->tableWidget_2->item(i,2)->text();
info.stu_age=ui->tableWidget_2->item(i,3)->text().toUInt();
info.stu_grade=ui->tableWidget_2->item(i,4)->text().toUInt();
info.stu_class=ui->tableWidget_2->item(i,5)->text().toUInt();
info.stu_id=ui->tableWidget_2->item(i,6)->text().toUInt();
info.stu_phone=ui->tableWidget_2->item(i,7)->text();
info.stu_wechat=ui->tableWidget_2->item(i,8)->text();
m_dlgAddstu.setType(false,info);
m_dlgAddstu.exec();
}
updateTable(); //更新完之后把界面刷新一下
}
清空学生表
//清除学生表
void MainWindow::on_btn_StuClear_clicked()
{
m_ptrStusql->clearStuInfo();
updateTable();
}
优化
优化一下数据模拟的加载时间
也就是优化一下add()函数
我们用QList<StuInfo> l来接收所有的添加信息,再通过循环从l里读取每条记录进行,执行添加sql语句,再把事务打开.
//添加学生
bool stusql::addstu(QList<StuInfo> l)
{
QSqlQuery sql(m_db);
m_db.transaction(); //开启事务
for(auto info:l)
{
QString strsql = QString("INSERT INTO student VALUES (NULL, '%1', %2, %3, %4, %5, '%6', '%7')")
.arg(info.stu_name)
.arg(info.stu_age)
.arg(info.stu_grade)
.arg(info.stu_class)
.arg(info.stu_id)
.arg(info.stu_phone)
.arg(info.stu_wechat);
if (!sql.exec(strsql)) {
QMessageBox::critical(nullptr, tr("Database Error"),
tr("Failed to insert data: %1").arg(sql.lastError().text()));
return false; // 返回 false 表示插入失败
}
}
m_db.commit();
return true; // 返回 true 表示插入成功
}
打包
样式打包
把我们的皮肤样式复制两份到当前目录,分别重名为dlg.css,main.css:
在dlg.css里只保留登录界面的样式,在main.css里只保留主界面的样式
在资源文件里把我们的所有资源都载入:
然后在主界面初始化的时候把我们的皮肤加载上:
数据库打包
数据库路径问题.我们把1端口打开,用当前目录下的路径,不要用绝对路径:
然后我们以debug方式打包我们的exe文件,打开QT安装目录下bin目录,在路径栏里输入"cmd",然后在dos窗户输入:"windeployqt.exe":
然后把我们的exe文件拖上去就开始打包了:
打包完成之后双击我们的exe文件发现运行不了:
这是QT的一个bug,有几个文件是不会打包的,需要我们手动打包.我们去bin目录下找到三个lib开头的文件,将其复制到打包好的exe文件同级目录下: