上一章节我们已经通过用户注册和登录功能初步接触了数据库,主要是通过QSqlQuery来与数据库进行交互,这种方式呢有一定局限性,需要比较懂sql语句,而且调用起来比较麻烦。下面我们通过使用QSqlTableModel来和数据库交互,QSqlTableModel是一个Qt封装好的数据库模型类,关联好数据库和数据表之后,我们只需要和它打交道就可以操控数据库啦。

目录

1、创建数据表

2、构建UI

3、增加数据

4、查询数据

5、修改数据

6、删除数据

7、总结

1、创建数据表
现在数据库中只有一个简单的用户表,用来记录用户数据,我们接下来向数据库中添加其他数据表,用来记录供应商信息、商品信息等。

创建表格之前还是先设计表结构,下面是我设计的商家表和商品表的表结构,当然,你可以按照自己的实际情况去设计,这里只是一个示例。表结构一般也会随着开发过程不断调整,但最好是在开始能设计的合理一些,减少一些不必要的调整。

供应商信息表的表结构设计如下:

qt sqlite 清空数据库 qt数据库增删改查_数据库

 商品信息表的表结构设计如下:

qt sqlite 清空数据库 qt数据库增删改查_开发语言_02

我们在mySqlite中的creatTable()中增加创建其他表格的语句,如下:

bool mySqlite::createTable()
 {
     query=new QSqlQuery;
     QString userStr = "create table if not exists user("
                       "[id] integer primary key autoincrement,"
                       "[name] varchar(30),"
                       "[password] varchar(30),"
                       "[role] varchar(30)"
                       ")";
     QString supplierStr = "create table if not exists supplier("
                           "[id] integer primary key autoincrement,"
                           "[name] varchar(30),"
                           "[addr] varchar(30),"
                           "[date] varchar(30),"
                           "[category] varchar(30),"
                           "[goodsCount] integer,"
                           "[contact] varchar(30),"
                           "[telephone] varchar(30)"
                           ")";
     QString goodsStr = "create table if not exists goods("
                        "[id] integer primary key autoincrement,"
                        "[name] varchar(30),"
                        "[category] varchar(30),"
                        "[speci] varchar(30),"
                        "[addr] varchar(30),"
                        "[brand] varchar(30),"
                        "[manu] varchar(30),"
                        "[note] varchar(30)"
                        ")";
     if(!(query->exec(userStr)&&query->exec(supplierStr)&&query->exec(goodsStr)))
         return false;
     return true;
 }

运行之后,用sqliteman查看之后,可以看到数据库中已经添加好了这两张表。

qt sqlite 清空数据库 qt数据库增删改查_qt_03

2、构建UI
接下来我们在supplier和goods两个页签中补充完整的内容。

首先,我们在mainwindow头文件中声明一个QSqlTableModel* supplierModel,再增加一个函数,就叫creatSupplierPage()吧,返回类型为QWidget,函数体内容如下:

QWidget *MainWindow::creatSupplierPage()
 {
     QWidget *supplierPage = new QWidget;
  
     QLabel *titleLabel = new QLabel("供应商信息");
     QPushButton *addButton = new QPushButton("添加");
     QHBoxLayout *titleLayout = new QHBoxLayout;
     titleLayout->addWidget(titleLabel);
     titleLayout->addStretch();
     titleLayout->addWidget(addButton);
  
     QLabel *idLabel = new QLabel("商家编号");
     QLineEdit *idEdit = new QLineEdit;
     QLabel *nameLabel = new QLabel("商家名称");
     QLineEdit *nameEdit = new QLineEdit;
     QLabel *addrLabel = new QLabel("所在地");
     QComboBox *addrEdit = new QComboBox;
     QLabel *dateLabel = new QLabel("添加日期");
     QDateEdit *dateEdit = new QDateEdit;
     QLabel *cateLabel = new QLabel("经营品类");
     QComboBox *cateEdit = new QComboBox;
     QPushButton *searchButton = new QPushButton("搜索");
  
     QHBoxLayout *sLayout_1 = new QHBoxLayout;
     sLayout_1->addWidget(idLabel);
     sLayout_1->addWidget(idEdit);
     sLayout_1->addStretch();
     sLayout_1->addWidget(nameLabel);
     sLayout_1->addWidget(nameEdit);
     sLayout_1->addStretch();
     sLayout_1->addWidget(addrLabel);
     sLayout_1->addWidget(addrEdit);
     sLayout_1->addStretch();
     sLayout_1->addWidget(dateLabel);
     sLayout_1->addWidget(dateEdit);
  
     QHBoxLayout *sLayout_2 = new QHBoxLayout;
     sLayout_2->addWidget(cateLabel);
     sLayout_2->addWidget(cateEdit);
     sLayout_2->addStretch();
     sLayout_2->addWidget(searchButton);
  
     QVBoxLayout *sLayout = new QVBoxLayout;
     sLayout->addLayout(sLayout_1);
     sLayout->addLayout(sLayout_2);
     QFrame *sFrame = new QFrame;
     sFrame->setFrameStyle(QFrame::StyledPanel);
     sFrame->setLayout(sLayout);
  
     supplierModel = new QSqlTableModel(supplierPage, mysql->myDB);//关联数据库
     supplierModel->setTable("supplier");//选择数据表
     supplierModel->setEditStrategy(QSqlTableModel::OnManualSubmit);//设置保存策略为手动提交
     supplierModel->setHeaderData(0,Qt::Horizontal, "序号");
     supplierModel->setHeaderData(1,Qt::Horizontal, "商家名称");
     supplierModel->setHeaderData(2,Qt::Horizontal, "所在地");
     supplierModel->setHeaderData(3,Qt::Horizontal, "添加日期");
     supplierModel->setHeaderData(4,Qt::Horizontal, "经营类目");
     supplierModel->setHeaderData(5,Qt::Horizontal, "商品数量");
     supplierModel->setHeaderData(6,Qt::Horizontal, "联系人");
     supplierModel->setHeaderData(7,Qt::Horizontal, "联系方式");
     supplierModel->select(); //选取整个表的所有行
  
     QTableView *tableView = new QTableView(this);
     tableView->setModel(supplierModel);
     tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);//使其不可编辑
  
     QVBoxLayout *layout = new QVBoxLayout;
     layout->addLayout(titleLayout);
     layout->addWidget(sFrame);
     layout->addWidget(tableView);
     supplierPage->setLayout(layout);
     return supplierPage;
 }

这个函数主要是实现了一个widget控件,这个控件就是按照咱们的原型设计来实现的,上部分是信息检索输入区,通过label、lineEdit、dateEdit、comboBox、pushButton等控件以及各种横向和纵向的layout来布局,并放到一个QFrame中框起来。

下半部分是一个QTableView,简单来说就是个表格,这个表格将我们的QSqlTableModel对象supplierModel置入,supplierMode将我们的数据库作为参数传入,并选择数据库中的supplier表格。

接下来我们将creatStackWidget()中第二个标签页中的label改为我们刚才新建的这个widget。

void MainWindow::creatStackWidget()
 {
     stackWidget = new QStackedWidget;
  
     QLabel *label1 = new QLabel("1");
     QWidget *supplierPage = creatSupplierPage();
     QLabel *label3 = new QLabel("3");
     QLabel *label4 = new QLabel("4");
     QLabel *label5 = new QLabel("5");
     QLabel *label6 = new QLabel("6");
     stackWidget->addWidget(label1);
     stackWidget->addWidget(supplierPage);
     stackWidget->addWidget(label3);
     stackWidget->addWidget(label4);
     stackWidget->addWidget(label5);
     stackWidget->addWidget(label6);
     setCentralWidget(stackWidget);
 }

运行之后,点击“供应商管理”,可以看到我们新建的供应商分页已经能显示出来啦。

qt sqlite 清空数据库 qt数据库增删改查_开发语言_04

3、增加数据
接下来我们实现添加供应商信息。

首先我们需要构建一个对话框来接收用户输入的供应商信息。

我们添加一个类,类名称我这里命名为“addSupplierDialog”,基本类我们选择custom。

建好类后,我们打开头文件,将内容修改如下,即该类是继承于QDialog,并声明了一些输入类控件,用来获取用户输入的信息:

#ifndef ADDSUPPLIERDIALOG_H
 #define ADDSUPPLIERDIALOG_H
  
 #include <QDialog>
 #include <QLabel>
 #include <QLineEdit>
 #include <QDateEdit>
 #include <QComboBox>
 #include <QPushButton>
  
 class addSupplierDialog : public QDialog
 {
     Q_OBJECT
  
 public:
     addSupplierDialog(QWidget *parent = nullptr);
     ~addSupplierDialog();
  
     QLineEdit *nameEdit;
     QComboBox *addrEdit;
     QComboBox *categoryEdit;
     QLineEdit *contactEdit;
     QLineEdit *teleEdit;
     QPushButton *addButton;
 };
  
 #endif // ADDSUPPLIERDIALOG_H

我们再打开cpp文件,将构造函数修改如下,完成对话框的界面。

#include "addsupplierdialog.h"
 #include <QGridLayout>
  
 addSupplierDialog::addSupplierDialog(QWidget *parent)
     : QDialog(parent)
 {
     QLabel *nameLabel = new QLabel("商家名称");
     nameEdit = new QLineEdit;
     QLabel *addrLabel = new QLabel("商家所在地");
     addrEdit = new QComboBox;
     QStringList addrList;
     addrList<<"北京"<<"上海"<<"广州"<<"深圳"<<"重庆";
     addrEdit->addItems(addrList);
     QLabel *categoryLabel = new QLabel("经营类目");
     categoryEdit = new QComboBox;
     QStringList categoryList;
     categoryList<<"家电"<<"数码"<<"家居"<<"服饰"<<"食品";
     categoryEdit->addItems(categoryList);
     QLabel *contactLabel = new QLabel("联系人");
     contactEdit = new QLineEdit;
     QLabel *teleLabel = new QLabel("联系方式");
     teleEdit = new QLineEdit;
     addButton = new QPushButton("添加");
  
     QGridLayout *layout = new QGridLayout;
     layout->addWidget(nameLabel,0,0);
     layout->addWidget(nameEdit,0,1);
     layout->addWidget(addrLabel,1,0);
     layout->addWidget(addrEdit,1,1);
     layout->addWidget(categoryLabel,2,0);
     layout->addWidget(categoryEdit,2,1);
     layout->addWidget(contactLabel,3,0);
     layout->addWidget(contactEdit,3,1);
     layout->addWidget(teleLabel,4,0);
     layout->addWidget(teleEdit,4,1);
     layout->addWidget(addButton,5,1);
  
     setLayout(layout);
     setWindowModality(Qt::WindowModal);
 }

接下来,我们回到mainwindow.h中,将addsupplierdialog.h引入,并在mainwindow类中声明一个addSupplierDialog的实例对象:

addSupplierDialog *supplierDialog;
我们再声明一个槽函数,用来接收“添加”按钮触发后的信号,函数名就命名为addSupplier吧。

void addSupplier();
我们在mainwindow.cpp的creat中将“添加”按钮和槽函数addSupplier()关联在一起,并将addSupplier()函数体补充完整。

connect(addButton,&QPushButton::clicked,this,&MainWindow::addSupplier);

qt sqlite 清空数据库 qt数据库增删改查_qt sqlite 清空数据库_05


void MainWindow::addSupplier()
 {
     supplierAddDialog = new addSupplierDialog(this);
     supplierAddDialog->show();
     connect(supplierAddDialog->addButton,&QPushButton::clicked,this,&MainWindow::insertSupplierData);
 }

即点击“添加”按钮之后,添加对话框初始化并显示出来,同时,将对话框中的“添加”按钮与一个叫insertSupplierData的槽函数关联在一起。 

那insertSupplierData要实现哪些内容呢,这里就需要我们通过QSqlTableModel的实例supplierModel与数据库进行交互啦。

在头文件中声明好insertSupplierData后,我们将这个槽函数的内容补充如下:

void MainWindow::insertSupplierData()
 {
     QString supplierName = supplierDialog->nameEdit->text();
     QString supplierAddr = supplierDialog->addrEdit->currentText();
     QDate currentDate = QDateTime::currentDateTime().date();
     QString supplierDate = currentDate.toString("yyyy.MM.dd");
     QString suppliercategory = supplierDialog->categoryEdit->currentText();
     QString supplierContact = supplierDialog->contactEdit->text();
     QString supplierTele = supplierDialog->teleEdit->text();
  
     QSqlRecord record = supplierModel->record();
     record.setValue(1,supplierName);
     record.setValue(2,supplierAddr);
     record.setValue(3,supplierDate);
     record.setValue(4,suppliercategory);
     record.setValue(6,supplierContact);
     record.setValue(7,supplierTele);
     supplierModel->insertRecord(supplierModel->rowCount(), record);
     supplierModel->submitAll();
 }

运行一下,我们在供应商信息添加按钮中输入一些测试数据,然后点击“添加”,可以看到,添加的信息已经保存在数据库中,并在tableView中显示出来了。

qt sqlite 清空数据库 qt数据库增删改查_数据库_06

 

qt sqlite 清空数据库 qt数据库增删改查_开发语言_07

这里商品数量我们还没有具体数据,后续我们会和其他表做关联获取具体的数据后,将这块儿补充完整。

4、查询数据
我们希望用户可以通过“商户名称”、“商户名称”、“商户所在地”、“添加日期”、“经营品类”作为查询项来查询数据库信息。

我们在mainwindow中新建一个槽函数:void searchSupplierData();

槽函数内容如下:

void MainWindow::searchSupplierData()
 {
     QString id =  QString("id = '%1'").arg(supplierIdEdit->text());
     QString name =  QString("name = '%1'").arg(supplierNameEdit->text());
     QString address = QString("addr = '%1'").arg(supplierAddrEdit->currentText());
     QString date = QString("date = '%1'").arg(supplierDateEdit->date().toString("yyyy.MM.dd"));
     QString category = QString("category = '%1'").arg(supplierCateEdit->currentText());
     QString filterStr = "";
     if(!supplierIdEdit->text().isEmpty())
         filterStr.append(id);
     if(!supplierNameEdit->text().isEmpty())
     {
         if(!filterStr.isEmpty())
             filterStr.append(" and ");
         filterStr.append(name);
     }
     if(!supplierAddrEdit->currentText().isEmpty())
     {
         if(!filterStr.isEmpty())
             filterStr.append(" and ");
         filterStr.append(address);
     }
     if(!filterStr.isEmpty())
         filterStr.append(" and ");
     filterStr.append(date);
     if(!supplierCateEdit->currentText().isEmpty())
     {
         if(!filterStr.isEmpty())
             filterStr.append(" and ");
         filterStr.append(category);
     }
     supplierModel->setFilter(filterStr);
     supplierModel->select();
 }

这里我们构建了一个过滤器filter,然后用QSqlTableModel的setFilter查询出符合条件的数据。

我们可以运行测试一下,发现可以正常查询出符合条件的数据。

5、修改数据
接下来我们来实现修改信息的功能。

我们在mainwindow中增加一个槽函数void modifySupplier();,用来处理修改按钮触发后的操作。

槽函数的内容如下:

void MainWindow::modifySupplier()
 {
     supplierModifyDialog = new modifySupplierDialog(this);
     int curRow = supplierTableView->currentIndex().row();
     QSqlRecord record = supplierModel->record(curRow);
  
     QString name = record.value(1).toString();
     supplierModifyDialog->nameEdit->setText(name);
     QString address = record.value(2).toString();
     supplierModifyDialog->addrEdit->setCurrentText(address);
     QString category = record.value(4).toString();
     supplierModifyDialog->categoryEdit->setCurrentText(category);
     QString contact = record.value(6).toString();
     supplierModifyDialog->contactEdit->setText(contact);
     QString telephone = record.value(7).toString();
     supplierModifyDialog->teleEdit->setText(telephone);
  
     connect(supplierModifyDialog->modifyButton,&QPushButton::clicked,this,&MainWindow::modifySupplierData);
     supplierModifyDialog->show();
 }

可以看到,和添加数据一样,我们点击“修改”按钮后,需要弹出来一个对话框,对话框将用户选择的数据显示出来并支持用户修改。

下面我们看看这个“修改对话框”是如何实现的:

我们新建一个类,命名为modifySupplierDialog,基础类为自定义。

新建成功后,我们打开其头文件,修改如下:

#ifndef MODIFYSUPPLIERDIALOG_H
 #define MODIFYSUPPLIERDIALOG_H
  
 #include <QDialog>
 #include <QLabel>
 #include <QLineEdit>
 #include <QDateEdit>
 #include <QComboBox>
 #include <QPushButton>
  
 class modifySupplierDialog : public QDialog
 {
     Q_OBJECT
  
 public:
     modifySupplierDialog(QWidget *parent = nullptr);
     ~modifySupplierDialog();
  
     QLineEdit *nameEdit;
     QComboBox *addrEdit;
     QComboBox *categoryEdit;
     QLineEdit *contactEdit;
     QLineEdit *teleEdit;
     QPushButton *modifyButton;
 };
  
 #endif // MODIFYSUPPLIERDIALOG_H

然后我们打开它的cpp文件,将其构造函数补充完整。

difysupplierdialog.h"
 #include <QGridLayout>
 modifySupplierDialog::modifySupplierDialog(QWidget *parent)
     : QDialog(parent)
 {
     QLabel *nameLabel = new QLabel("商家名称");
     nameEdit = new QLineEdit;
     QLabel *addrLabel = new QLabel("商家所在地");
     addrEdit = new QComboBox;
     QStringList addrList;
     addrList<<"北京"<<"上海"<<"广州"<<"深圳"<<"重庆";
     addrEdit->addItems(addrList);
     QLabel *categoryLabel = new QLabel("经营类目");
     categoryEdit = new QComboBox;
     QStringList categoryList;
     categoryList<<"家电"<<"数码"<<"家居"<<"服饰"<<"食品";
     categoryEdit->addItems(categoryList);
     QLabel *contactLabel = new QLabel("联系人");
     contactEdit = new QLineEdit;
     QLabel *teleLabel = new QLabel("联系方式");
     teleEdit = new QLineEdit;
     modifyButton = new QPushButton("修改");
     QGridLayout *layout = new QGridLayout;
     layout->addWidget(nameLabel,0,0);
     layout->addWidget(nameEdit,0,1);
     layout->addWidget(addrLabel,1,0);
     layout->addWidget(addrEdit,1,1);
     layout->addWidget(categoryLabel,2,0);
     layout->addWidget(categoryEdit,2,1);
     layout->addWidget(contactLabel,3,0);
     layout->addWidget(contactEdit,3,1);
     layout->addWidget(teleLabel,4,0);
     layout->addWidget(teleEdit,4,1);
     layout->addWidget(modifyButton,5,1);
     setLayout(layout);
     setWindowModality(Qt::WindowModal);
 }
 modifySupplierDialog::~modifySupplierDialog()
 {
 }

在mainwindow.cpp中将修改按钮的信号和槽函数连接起来:

QPushButton *searchButton = new QPushButton("搜索");
     connect(searchButton,&QPushButton::clicked,this,&MainWindow::searchSupplierData);


运行之后,选中表中有数据的某一行,点击“修改”按钮,可以看到弹出了修改对话框,对话框中的输入控件回显需要修改的数据。

qt sqlite 清空数据库 qt数据库增删改查_开发语言_08

用户修改信息后点击修改对话框中的“修改”按钮,则调用了我们定义的另一个槽函数void modifySupplierData(),将数据重新写入数据库中。

void MainWindow::modifySupplierData()
 {
     QString supplierName = supplierModifyDialog->nameEdit->text();
     QString supplierAddr = supplierModifyDialog->addrEdit->currentText();
     QString suppliercategory = supplierModifyDialog->categoryEdit->currentText();
     QString supplierContact = supplierModifyDialog->contactEdit->text();
     QString supplierTele = supplierModifyDialog->teleEdit->text();
  
     int curRow = supplierTableView->currentIndex().row();
     QSqlRecord record = supplierModel->record(curRow);
     record.setValue(1,supplierName);
     record.setValue(2,supplierAddr);
     record.setValue(4,suppliercategory);
     record.setValue(6,supplierContact);
     record.setValue(7,supplierTele);
  
     if(supplierModel->setRecord(curRow, record))
     {
         supplierModifyDialog->close();
         supplierModel->submitAll();
         supplierTableView->setEnabled(true);
     }
 }

运行之后,修改某行数据,可以看到修改成功。

qt sqlite 清空数据库 qt数据库增删改查_开发语言_09

 

qt sqlite 清空数据库 qt数据库增删改查_qt sqlite 清空数据库_10

6、删除数据
接下来我们实现删除数据库的某条数据。

在mainwindow中声明一个槽函数void deleteSupplierData();

函数体如下:

void MainWindow::deleteSupplierData()
 {
     int curRow = supplierTableView->currentIndex().row();
     supplierModel->removeRow(curRow);
     int ok = QMessageBox::warning(this,tr("删除当前行!"),
                                       tr("你确定删除当前行吗?"),
                                       QMessageBox::Yes,QMessageBox::No);
         if(ok == QMessageBox::No)
             supplierModel->revertAll(); //如果不删除,则撤销
         else
             supplierModel->submitAll(); //否则提交,在数据库中删除该行
 }


先获取用户所选择的行数,然后调用removeRow,这里设置了一个二次确认的弹窗,用户点击“yes”,删除成功,用户点击“no”,则取消删除。

连接按钮信号和槽函数,运行一下,可以看到,点击“删除”按钮可以成功删除选中的数据行。

qt sqlite 清空数据库 qt数据库增删改查_开发语言_11

 

qt sqlite 清空数据库 qt数据库增删改查_qt_12

7、总结
这一章节,我们通过使用QSqlTableModel这个类的实例,来与数据库交互,实现了数据的增、删、改、查,后续其他的页面,包括“商品管理”、“库存管理”等页面,也都可以按照这个思路和方法来实现。