程序系统内部的内存存储是在程序关闭后进行自动清除,这对我们记录信息和使用过程都有着极大的影响,若想做出适合平时使用的系统,结合数据库进行系统开发是最普遍和常见的方式
本文通过Qt和SQL进行结合,开发出商品库存管理系统,可以记录商品的总量,剩余量,品牌,类型以及金额,并通过数据库对数据进行存储。
Qt中提供的QSqlQuery类适用于连接各种类型的数据库,本文连接的是MySql数据库,出现连接问题参考上文。
数据表结构的设计一定要符合系统需要,本系统设计了类型表和品牌表,结构如下:
类型表 品牌表
Sql语句如下:
create table type(id1 int primary key,name text);
create table brand(id2 int primary key, name text,type text,price int,sum int,sell int,last int);
系统主要使用了QSqlQuery类中的方法与数据库进行联动,同时通过将ui代码载入系统进行本窗体切换不同界面,实现一个窗体完成各种功能。
首先设计不同界面的UI
主体ui界面
查询商品ui界面
ui代码生成如下:
1、打开Qt 5.12.9 for Desktop (MinGW 7.3.0 32 bit)命令行
2、切换到QT项目的路径
3、输入uic-= ui.h widget.ui
(ui文件生成.h头文件)
将生成的文件复制进入主窗体
头文件添加(选择有用的进行复制)
widget文件添加:
此时通过show()和hide()就可以控制窗体的显示和隐藏。
对多个界面进行初始化和隐藏,同时对数据库进行连接操作,同时写入sql语句进行建表和插入数据
void Widget::Init() { setSelectForm(this); setPasssWdForm(this); wid_select->hide(); wid_password->hide(); QString filename = "test"; QFileInfo info(filename); bool ret = info.exists(); db = QSqlDatabase::addDatabase("QMYSQL"); db.setDatabaseName(filename); db.setHostName("localhost"); db.setUserName("root"); db.setPassword("root"); db.setPort(3306); QSqlQuery query(db); bool ok = db.open(); if(ok) { //创建分类表 QString cmd1 = "create table type(id1 int primary key,name text);"; query.exec(cmd1); query.exec(QString("insert into type values('0','请选择类型')")); query.exec(QString("insert into type values('01','电视')")); query.exec(QString("insert into type values('02','空调')")); //创建品牌表 QString cmd2 = "create table brand(id2 int primary key, name text," "type text,price int,sum int,sell int,last int);"; query.exec(cmd2); query.exec(QString("insert into brand values('01','海信','电视',3699,50,10,40)")); query.exec(QString("insert into brand values('02','创维','电视',3499,20,5,15)")); query.exec(QString("insert into brand values('03','海尔','电视',4199,80,40,40)")); query.exec(QString("insert into brand values('04','王牌','电视',3999,40,10,30)")); query.exec(QString("insert into brand values('05','海尔','空调',2899,60,10,50)")); query.exec(QString("insert into brand values('06','格力','空调',2799,70,20,50)")); qDebug()<
读取type数据将其载入combox,同时对自定义的信号进行绑定
void Widget::InitData() { QString sel1 = "select name from type"; QSqlQuery query(db); query.exec(sel1); QStringList listName; while(query.next()) { listName<cbox_type->addItems(listName); cbox_select_type->addItems(listName); connect(cbox_select_type,SIGNAL(currentTextChanged(QString)) ,this,SLOT(on_cbox_type_currentTextChanged(QString))); connect(btn_select_select,SIGNAL(clicked(bool)),this,SLOT(doProcessClickSelect(bool))); }
将各个按钮进行槽功能绑定,分别对应隐藏和显示不同的界面,以商品入库和信息查询界面为例
void Widget::on_btn_storage_clicked() { wid_select->hide(); wid_password->hide(); ui->wid_sell->show(); ui->lbl_sell->setText("商品入库"); }
void Widget::on_btn_select_clicked() { ui->wid_sell->hide(); wid_password->hide(); wid_select->show(); ui->lbl_sell->setText("商品查询"); }
商品查询功能通过商品的品牌和类型对已存商品进行查询
从ui控件中的combox处获取值并加入SQL语句中
QString sel2 = QString("select * from brand where name = '%1' and type='%2'") .arg(cbox_select_brand->currentText()) .arg(cbox_select_type->currentText());
然后通过append在文本框进行显示信息
query.exec(sel2); QString msg; while(query.next()) { msg+= "品牌名称:"+query.value(1).toString()+"\n"; msg+= "商品类型:"+query.value(2).toString()+"\n"; msg+= "商品价格:"+query.value(3).toString()+"\n"; msg+= "商品总数:"+query.value(4).toString()+"\n"; msg+= "售出数量:"+query.value(5).toString()+"\n"; msg+= "剩余数量:"+query.value(6).toString()+"\n"; } tedit_select_show->append(msg);
结果如下:
由于初始化只进行了类型的读取,为了使类型和品牌进行联动,定义一个combox中选项改变的信号传入槽中,对选中的类型进行SQL查询并添加到品牌的combox进行显示
void Widget::on_cbox_type_currentTextChanged(const QString &arg1) { QSqlQuery query(db); QString sel2 = QString("select name from brand where type = '%1'").arg(arg1); query.exec(sel2); QStringList listProduct; while(query.next()) { listProduct<cbox_brand->clear(); ui->cbox_brand->addItems(listProduct); cbox_select_brand->clear(); cbox_select_brand->addItems(listProduct); }
当点击商品添加的确定按钮时,要对添加的数据进行接收,并通过SQL语句将其传入数据库中,此处可以采用prepare方法,将SQL语句写入prepare方法中,需要替换的数据前面加上":",并通过bindValue()方法进行替换。
if(text == "商品添加") { int maxNum = 0; QSqlQuery query(db); QString cmd = "select max(id2) from brand"; query.exec(cmd); if(query.next()) { maxNum = query.value(0).toString().toInt(); maxNum += 1; query.prepare("INSERT INTO brand (id2, name, type,price,sum,sell,last) VALUES (:id2, :name, :type,:price,:sum,:sell,:last)"); query.bindValue(":id2", maxNum); query.bindValue(":name", ui->cbox_brand->currentText()); query.bindValue(":type", ui->cbox_type->currentText()); query.bindValue(":price", ui->ledit_price->text()); query.bindValue(":sum", ui->sbox_num->text()); query.bindValue(":sell", ui->sbox_num->text()); query.bindValue(":last", ui->sbox_num->text()); bool ret = query.exec(); if(ret) { QMessageBox::information(this,"提示","保存成功",QMessageBox::Ok); } else { QMessageBox::information(this,"提示","保存失败",QMessageBox::Ok); } } else { return; } }
商品入库功能主要是对已经在库的商品进行数量上的操作,因此通过SQL中的UPDATE进行相对应的操作,同样使用prepare方法,因为入库需要查询相对应的商品,因此通过类型、品牌、价格进行查询判断,并记录下商品的id,未查询到提示用户先进行商品添加。
if(text == "商品入库") { int id = 0; int sum = 0; int last = 0; QSqlQuery query(db); QString type = ui->cbox_type->currentText(); QString brand = ui->cbox_brand->currentText(); QString price = ui->ledit_price->text(); QString cmd = QString("select id2,sum,last from brand where type = '%1' and name = '%2' and price = '%3'").arg(type).arg(brand).arg(price); query.exec(cmd); if(query.next()) { id = query.value(0).toInt(); sum = query.value(1).toInt(); last = query.value(2).toInt(); sum += ui->sbox_num->text().toUInt(); last += ui->sbox_num->text().toUInt(); query.prepare("UPDATE brand SET sum = :sum,last = :last WHERE id2 = :id"); query.bindValue(":sum", sum); query.bindValue(":last", last); query.bindValue(":id", id); bool ret = query.exec(); if(ret) { QMessageBox::information(this,"提示","入库成功",QMessageBox::Ok); } else { QMessageBox::information(this,"提示","入库失败",QMessageBox::Ok); } } else { QMessageBox::information(this,"错误","未找到商品",QMessageBox::Ok); } }
出售商品与商品入库操作相似,主要是对已售出商品数量和剩余商品数量进行对应的操作,通过查询商品剩余数量对售出数量进行相应的操作,提示用户商品是否缺货。
if(text == "出售商品") { int id,sum,sell,last = 0; QSqlQuery query(db); QString type = ui->cbox_type->currentText(); QString brand = ui->cbox_brand->currentText(); QString price = ui->ledit_price->text(); QString cmd = QString("select id2,sum,sell,last from brand where type = '%1' and name = '%2' and price = '%3'").arg(type).arg(brand).arg(price); bool ret = query.exec(cmd); if(query.next()) { id = query.value(0).toInt(); sum = query.value(1).toInt(); sell = query.value(2).toInt(); last = query.value(3).toInt(); if(last>0) { int last1 = ui->sbox_num->text().toUInt(); sell += ui->sbox_num->text().toUInt(); if(last>=last1) { last -= ui->sbox_num->text().toUInt(); query.prepare("update brand set sell = :sell,last = :last where id2 = :id2"); query.bindValue(":sell",sell); query.bindValue(":last",last); query.bindValue(":id2",id); bool ret = query.exec(); if(ret) { QMessageBox::information(this,"提示","售出成功",QMessageBox::Ok); } else { QMessageBox::information(this,"提示","售出失败",QMessageBox::Ok); } } else { QMessageBox::information(this,"提示","商品缺货",QMessageBox::Ok); } } else { QMessageBox::information(this,"提示","商品缺货",QMessageBox::Ok); } } }