十一、Qt数据库操作

一、Sql介绍

Qt Sql模块包含多个类,实现数据库的连接,Sql语句的执行,数据获取与界面显示,数据与界面直接使用Model/View结构。

1、使用Sql模块

(1)工程加入

QT += sql

(2)添加头文件

#include <QtSel>

2、Sql相关类

1、数据库相关类

  • QTableView:常用的数据库内容显示组件
  • QSalQuryModel:通过设置select语句查询获取数据库内容,数据只读。
  • QSqlTableModel:直接设置一个数据表的名称,可以获取苏韩剧表的全部记录,可以编辑。
  • QSqlRelationalTableModel:为单张的数据库表提供了一个编辑的数据模型,支持外键。

二、QSqltableModel

1、实现程序

在这里插入图片描述

(1)创建项目,基于QMainWindow

(2)添加类

在这里插入图片描述

(3)添加组件

在这里插入图片描述

(4)加载数据库

void MainWindow::openTable()
{tabModel = new QSqlTableModel(this, DB);tabModel->setTable("employee"); //设置数据表名称tabModel->setSort(tabModel->fieldIndex("empNo"), Qt::AscendingOrder); //按照员工号升序tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit); //手动提交数据if(!tabModel->select()){QMessageBox::critical(this, "错误", "打开数据表错误,错误信息\n"+ tabModel->lastError().text());return;}// 修改表头tabModel->setHeaderData(tabModel->fieldIndex("empNo"), Qt::Horizontal, "工号");tabModel->setHeaderData(tabModel->fieldIndex("Name"), Qt::Horizontal, "姓名");tabModel->setHeaderData(tabModel->fieldIndex("Gender"), Qt::Horizontal, "性别");tabModel->setHeaderData(tabModel->fieldIndex("Height"), Qt::Horizontal, "身高");tabModel->setHeaderData(tabModel->fieldIndex("Birthday"), Qt::Horizontal, "出生日期");tabModel->setHeaderData(tabModel->fieldIndex("Mobile"), Qt::Horizontal, "手机号");tabModel->setHeaderData(tabModel->fieldIndex("Province"), Qt::Horizontal, "省份");tabModel->setHeaderData(tabModel->fieldIndex("City"), Qt::Horizontal, "城市");tabModel->setHeaderData(tabModel->fieldIndex("Depart"), Qt::Horizontal, "部门");tabModel->setHeaderData(tabModel->fieldIndex("Education"), Qt::Horizontal, "学历");tabModel->setHeaderData(tabModel->fieldIndex("Salary"), Qt::Horizontal, "薪资");tabModel->setHeaderData(tabModel->fieldIndex("Photo"), Qt::Horizontal, "照片");tabModel->setHeaderData(tabModel->fieldIndex("Memo"), Qt::Horizontal, "备注");theSelection = new QItemSelectionModel(tabModel);ui->tableView->setModel(tabModel);ui->tableView->setSelectionModel(theSelection);connect(theSelection, SIGNAL(currentChanged(QModelIndex, QModelIndex)),this, SLOT(on_currentChanged(QModelIndex, QModelIndex)));connect(theSelection, SIGNAL(currentRowChanged(QModelIndex, QModelIndex)),this, SLOT(on_currentRowChanged(QModelIndex, QModelIndex)));// 隐藏列ui->tableView->setColumnHidden(tabModel->fieldIndex("Photo"), true);ui->tableView->setColumnHidden(tabModel->fieldIndex("Memo"), true);dataMapper = new QDataWidgetMapper;dataMapper->setModel(tabModel);dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);dataMapper->addMapping(ui->spinBoxNum, tabModel->fieldIndex("empNo"));dataMapper->addMapping(ui->lineEditName, tabModel->fieldIndex("Name"));dataMapper->addMapping(ui->comboBoxSex, tabModel->fieldIndex("Gender"));dataMapper->addMapping(ui->doubleSpinBoxHeight, tabModel->fieldIndex("Height"));dataMapper->addMapping(ui->lineEditBirthday, tabModel->fieldIndex("Birthday"));dataMapper->addMapping(ui->lineEditPhone, tabModel->fieldIndex("Mobile"));dataMapper->addMapping(ui->comboBoxProvince, tabModel->fieldIndex("Province"));dataMapper->addMapping(ui->lineEditCity, tabModel->fieldIndex("City"));dataMapper->addMapping(ui->comboBoxWork, tabModel->fieldIndex("Depart"));dataMapper->addMapping(ui->comboBoxStudy, tabModel->fieldIndex("Education"));dataMapper->addMapping(ui->textEditInfo, tabModel->fieldIndex("Memo"));getFiledNames();ui->actOpen->setEnabled(false);ui->actAppend->setEnabled(true);ui->actDelete->setEnabled(true);ui->actInsert->setEnabled(true);ui->actScan->setEnabled(true);ui->groupBoxSort->setEnabled(true);ui->groupBoxFilter->setEnabled(true);// 使用delegate实现下拉选择QStringList strList;strList << "男" << "女";bool isEditable = false;delegateSex.setItem(strList, isEditable);ui->tableView->setItemDelegateForColumn(tabModel->fieldIndex("Gender"), &delegateSex);
}void MainWindow::getFiledNames()
{QSqlRecord emptyRec = tabModel->record();for (int i = 0; i < emptyRec.count(); ++i){ui->comboBoxFields->addItem(emptyRec.fieldName(i));}
}void MainWindow::on_currentChanged(const QModelIndex &current, const QModelIndex &preivous)
{Q_UNUSED(current)Q_UNUSED(preivous)ui->actSubmit->setEnabled(tabModel->isDirty()); // 是否有数据修改ui->actRevert->setEnabled(tabModel->isDirty()); // 是否有数据修改
}void MainWindow::on_currentRowChanged(const QModelIndex &current, const QModelIndex &preivous)
{ui->actDelete->setEnabled(current.isValid());ui->actAppend->setEnabled(current.isValid());ui->actInsert->setEnabled(current.isValid());if(! current.isValid()){ui->labelPhoto->clear();return;}dataMapper->setCurrentIndex(current.row());QSqlRecord curRec = tabModel->record(current.row());if(curRec.isNull("Photo")){ui->labelPhoto->clear();}else{QByteArray data  = curRec.value("Photo").toByteArray();QPixmap pic;pic.loadFromData(data);ui->labelPhoto->setPixmap(pic.scaledToWidth(ui->labelPhoto->size().width()));}
}void MainWindow::on_actOpen_triggered()
{QString fileName = QFileDialog::getOpenFileName(this, "选择数据库文件","", "Sqlite数据库(*.db *.db3)");if(fileName.isEmpty()){return;}DB = QSqlDatabase::addDatabase("QSQLITE"); //添加数据库驱动DB.setDatabaseName(fileName); // 设置数据库名称if(!DB.open()){QMessageBox::warning(this, "错误", "打开数据库失败");return;}openTable();
}

在这里插入图片描述

(5)实现工具栏按钮功能

void MainWindow::on_actAppend_triggered()
{tabModel->insertRow(tabModel->rowCount(), QModelIndex());QModelIndex curIndex = tabModel->index(tabModel->rowCount() - 1, 1); // 插入后增加一行theSelection->clearSelection();theSelection->setCurrentIndex(curIndex, QItemSelectionModel::Select);tabModel->setData(tabModel->index(curIndex.row(), 0), 2000 + tabModel->rowCount());tabModel->setData(tabModel->index(curIndex.row(), 2), "男");ui->actSubmit->setEnabled(true);ui->actRevert->setEnabled(true);
}void MainWindow::on_actInsert_triggered()
{QModelIndex curIndex = theSelection->currentIndex();tabModel->insertRow(curIndex.row(), QModelIndex());theSelection->clearSelection();theSelection->setCurrentIndex(curIndex, QItemSelectionModel::Select);tabModel->setData(tabModel->index(curIndex.row(), 0), 2000 + tabModel->rowCount());tabModel->setData(tabModel->index(curIndex.row(), 2), "男");ui->actSubmit->setEnabled(true);ui->actRevert->setEnabled(true);
}void MainWindow::on_actDelete_triggered()
{QModelIndex curIndex = theSelection->currentIndex();tabModel->removeRow(curIndex.row());ui->actSubmit->setEnabled(true);ui->actRevert->setEnabled(true);
}void MainWindow::on_actSubmit_triggered()
{bool result = tabModel->submitAll();if(!result){QMessageBox::information(this, "信息", "数据提交错误,错误信息\n"+ tabModel->lastError().text());}else{ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);}
}void MainWindow::on_actRevert_triggered()
{tabModel->revertAll();ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);
}void MainWindow::on_actSetPhoto_triggered()
{QString fileName = QFileDialog::getOpenFileName(this, "选择图片", "", "照片(*.jpg *.png)");if(fileName.isEmpty()){return;}QByteArray data;QFile *file = new QFile(fileName);if(file->open(QIODevice::ReadOnly)){data = file->readAll();QModelIndex curIndex = theSelection->currentIndex();QSqlRecord curRec = tabModel->record(curIndex.row());curRec.setValue("Photo", data);tabModel->setRecord(curIndex.row(), curRec);QPixmap pic;pic.load(fileName);ui->labelPhoto->setPixmap(pic.scaledToWidth(ui->labelPhoto->width()));file->close();}delete file;
}void MainWindow::on_actClearPhoto_triggered()
{QModelIndex curIndex = theSelection->currentIndex();QSqlRecord curRec = tabModel->record(curIndex.row());curRec.setNull("Photo");tabModel->setRecord(curIndex.row(), curRec);ui->labelPhoto->clear();
}void MainWindow::on_actScan_triggered()
{if(tabModel->rowCount() != 0){for (int i = 0; i < tabModel->rowCount(); ++i){QSqlRecord aRec = tabModel->record(i);float salary = aRec.value("Salary").toFloat();salary *= 1.1;aRec.setValue("Salary", salary);tabModel->setRecord(i, aRec);}if(tabModel->submitAll()){QMessageBox::information(this, "信息", "涨工资完成");}}
}void MainWindow::on_comboBoxFields_currentIndexChanged(int index)
{if(ui->rbtnAscend->isCheckable()){tabModel->setSort(index, Qt::AscendingOrder);}else{tabModel->setSort(index, Qt::DescendingOrder);}tabModel->select(); // 重新从数据库装载
}void MainWindow::on_rbtnAscend_clicked()
{tabModel->setSort(ui->comboBoxFields->currentIndex(), Qt::AscendingOrder);tabModel->select(); // 重新从数据库装载
}void MainWindow::on_rbtnDescend_clicked()
{tabModel->setSort(ui->comboBoxFields->currentIndex(), Qt::DescendingOrder);tabModel->select(); // 重新从数据库装载
}void MainWindow::on_rbtnMan_clicked()
{tabModel->setFilter("Gender='男'");
}void MainWindow::on_rbtnWoman_clicked()
{tabModel->setFilter("Gender='女'");
}void MainWindow::on_rbtnAll_clicked()
{tabModel->setFilter("");
}

三、QSqlQueryModel

1、相关类

QAbstractTableModelQSqlQueryModel //封装了指向SELECT语句从数据库查询数据的功能QSqlTableModelQSqlRelationalTableModel

2、实现程序

在这里插入图片描述

1、创建项目,基于QMainWindow

2、添加图标资源文件,添加工具按钮

3、添加组件

在这里插入图片描述

4、实现功能

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);qryModel = new QSqlQueryModel(this);theSelection = new QItemSelectionModel(qryModel);dataMapper = new QDataWidgetMapper(this);dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);dataMapper->setModel(qryModel);ui->tableView->setModel(qryModel);ui->tableView->setSelectionModel(theSelection);connect(theSelection, SIGNAL(currentRowChanged(QModelIndex, QModelIndex)),this, SLOT(on_currentRowChanged(QModelIndex, QModelIndex)));
}MainWindow::~MainWindow()
{delete ui;
}#include <QFileDialog>
#include <QMessageBox>
void MainWindow::on_actOpenDB_triggered()
{QString fileName = QFileDialog::getOpenFileName(this, "打开数据库", "","数据库文件(*.db *.db3)");if(fileName.isEmpty()){return;}DB = QSqlDatabase::addDatabase("QSQLITE");DB.setDatabaseName(fileName);if(!DB.open()){QMessageBox::warning(this, "错误", "打开数据库失败");return;}qryModel->setQuery("SELECT EmpNo,Name,Gender,Height,Birthday,Mobile,Province,City,Depart,Education,Salary FROM employee ORDER BY EMpNo", DB);if(qryModel->lastError().isValid()){QMessageBox::critical(this, "错误", "查询失败\n" + qryModel->lastError().text());return;}qryModel->setHeaderData(0, Qt::Horizontal, "工号");qryModel->setHeaderData(2, Qt::Horizontal, "性别");dataMapper->addMapping(ui->spinBoxNum, 0);dataMapper->addMapping(ui->lineEditName, 1);dataMapper->addMapping(ui->comboBoxSex, 2);dataMapper->addMapping(ui->doubleSpinBoxHeight, 3);dataMapper->addMapping(ui->lineEditBirthday, 4);dataMapper->addMapping(ui->lineEditPhone, 5);dataMapper->addMapping(ui->comboBoxProvince, 6);dataMapper->addMapping(ui->lineEditCity, 7);dataMapper->addMapping(ui->comboBoxWork, 8);dataMapper->addMapping(ui->comboBoxStudy, 9);dataMapper->addMapping(ui->textEditInfo, 10);// dataMapper->toFirst();ui->actOpenDB->setEnabled(false);}void MainWindow::on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{if(!current.isValid()){ui->labelPhoto->clear();return;}dataMapper->setCurrentModelIndex(current);bool first = (current.row() == 0);bool last = (current.row() == qryModel->rowCount() - 1);ui->actRecFirst->setEnabled(!first);ui->actRecPrevious->setEnabled(!first);ui->actRecNext->setEnabled(!last);ui->actRecLast->setEnabled(!last);int curRecNo = theSelection->currentIndex().row();QSqlRecord curRec = qryModel->record(curRecNo);int empNo = curRec.value("EmpNo").toInt();QSqlQuery query;query.prepare("select EmpNo,Memo,Photo from employee where EmpNo = :ID");query.bindValue(":ID", empNo); //防注入query.exec();query.first(); // 回到第一条记录if(qryModel->lastError().isValid()){QMessageBox::critical(this, "错误", "查询失败\n" + qryModel->lastError().text());return;}QVariant va = query.value("Photo");if(!va.isValid()){ui->labelPhoto->clear();}else{QPixmap pic;QByteArray data = va.toByteArray();pic.loadFromData(data);ui->labelPhoto->setPixmap(pic.scaledToWidth(ui->labelPhoto->size().width()));}QVariant va2 = query.value("Memo");ui->textEditInfo->setPlainText(va2.toString());
}void MainWindow::on_actRecFirst_triggered()
{dataMapper->toFirst();int index = dataMapper->currentIndex();QModelIndex curIndex = qryModel->index(index, 1);theSelection->clearSelection();theSelection->setCurrentIndex(curIndex, QItemSelectionModel::Select);
}void MainWindow::on_actRecPrevious_triggered()
{dataMapper->toPrevious();int index = dataMapper->currentIndex();QModelIndex curIndex = qryModel->index(index, 1);theSelection->clearSelection();theSelection->setCurrentIndex(curIndex, QItemSelectionModel::Select);
}void MainWindow::on_actRecNext_triggered()
{dataMapper->toNext();int index = dataMapper->currentIndex();QModelIndex curIndex = qryModel->index(index, 1);theSelection->clearSelection();theSelection->setCurrentIndex(curIndex, QItemSelectionModel::Select);
}void MainWindow::on_actRecLast_triggered()
{dataMapper->toLast();int index = dataMapper->currentIndex();QModelIndex curIndex = qryModel->index(index, 1);theSelection->clearSelection();theSelection->setCurrentIndex(curIndex, QItemSelectionModel::Select);
}

四、QSqlQuery

QSqlQuery是可以执行任意SQL语句的类,如SELECT、INSERT、UPDATE、DELETE等。

1、实现程序

在这里插入图片描述

(1)创建项目,基于QMainWindow

(2)添加工具栏按钮

(3)添加对话框

在这里插入图片描述
在这里插入图片描述

#include "dialogdata.h"
#include "ui_dialogdata.h"DialogData::DialogData(QWidget *parent) :QDialog(parent),ui(new Ui::DialogData)
{ui->setupUi(this);
}DialogData::~DialogData()
{delete ui;
}void DialogData::setUpdateRecord(QSqlRecord &recData)
{mRecord = recData;ui->spinBoxEmpNo->setEnabled(false);setWindowTitle("更新记录");// 更新界面ui->spinBoxEmpNo->setValue(recData.value("EmpNo").toInt());ui->lineEditName->setText(recData.value("Name").toString());ui->comboBoxSex->setCurrentText(recData.value("Gender").toString());ui->doubleSpinBoxHeight->setValue(recData.value("Height").toFloat());ui->lineEditBirthday->setText(recData.value("Birthday").toString());ui->lineEditPhone->setText(recData.value("Mobile").toString());ui->comboBoxProvince->setCurrentText(recData.value("Province").toString());ui->lineEditCity->setText(recData.value("City").toString());ui->comboBoxDepart->setCurrentText(recData.value("Depart").toString());ui->comboBoxEducation->setCurrentText(recData.value("Education").toString());ui->spinBoxSalary->setValue(recData.value("Salary").toInt());ui->textEditInfo->setText(recData.value("Memo").toString());QVariant va = recData.value("Photo");if(!va.isValid()){ui->labelPhoto->clear();}else{QByteArray data = va.toByteArray();QPixmap pic;pic.loadFromData(data);ui->labelPhoto->setPixmap(pic.scaledToWidth(ui->labelPhoto->size().width()));}
}void DialogData::setInsertRecord(QSqlRecord &recData)
{mRecord = recData;ui->spinBoxEmpNo->setEnabled(true);setWindowTitle("新建记录");ui->spinBoxEmpNo->setValue(recData.value("EmpNo").toInt());
}QSqlRecord DialogData::getRecordData()
{mRecord.setValue("EmpNo", ui->spinBoxEmpNo->value());mRecord.setValue("Name", ui->lineEditName->text());mRecord.setValue("Gender", ui->comboBoxSex->currentText());mRecord.setValue("Height", ui->doubleSpinBoxHeight->value());mRecord.setValue("Birthday", ui->lineEditBirthday->text());mRecord.setValue("Mobile", ui->lineEditPhone->text());mRecord.setValue("Province", ui->comboBoxProvince->currentText());mRecord.setValue("City", ui->lineEditCity->text());mRecord.setValue("Depart", ui->comboBoxDepart->currentText());mRecord.setValue("Education", ui->comboBoxEducation->currentText());mRecord.setValue("Salary", ui->spinBoxSalary->value());mRecord.setValue("Memo", ui->textEditInfo->toPlainText());return mRecord;
}#include <QFileDialog>
void DialogData::on_btnLoadPhoto_clicked()
{QString fileName = QFileDialog::getOpenFileName(this, "选择图片", "","图片(*.png *.jpg)");if(fileName.isEmpty()){return;}QByteArray data;QFile *file = new QFile(fileName);file->open(QIODevice::ReadOnly);data = file->readAll();file->close();delete file;mRecord.setValue("Photo", data);QPixmap pic;pic.loadFromData(data);ui->labelPhoto->setPixmap(pic.scaledToWidth(ui->labelPhoto->size().width()));
}void DialogData::on_btnClearPhoto_clicked()
{}

(4)工具栏按钮功能

#include "mainwindow.h"
#include "ui_mainwindow.h"#include <QMessageBox>#include "dialogdata.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);setCentralWidget(ui->tableView);qryModel = new QSqlQueryModel;theSelection = new QItemSelectionModel(qryModel);ui->tableView->setModel(qryModel);ui->tableView->setSelectionModel(theSelection);connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)),this, SLOT(on_TableView_doubleClicked(QModelIndex)));
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::openTable()
{qryModel->setQuery("SELECT EmpNo,Name,Gender,Height,Birthday,Mobile,Province,City,Depart,Education,Salary From employee order by EmpNo");if(qryModel->lastError().isValid()){QMessageBox::warning(this, "错误", "SqlCmdError" + qryModel->lastError().text());return;}qryModel->setHeaderData(0, Qt::Horizontal, "工号");qryModel->setHeaderData(1, Qt::Horizontal, "姓名");qryModel->setHeaderData(2, Qt::Horizontal, "性别");qryModel->setHeaderData(3, Qt::Horizontal, "身高");qryModel->setHeaderData(4, Qt::Horizontal, "出生日期");qryModel->setHeaderData(5, Qt::Horizontal, "手机");qryModel->setHeaderData(6, Qt::Horizontal, "省份");qryModel->setHeaderData(7, Qt::Horizontal, "城市");qryModel->setHeaderData(8, Qt::Horizontal, "部门");qryModel->setHeaderData(9, Qt::Horizontal, "学历");qryModel->setHeaderData(10, Qt::Horizontal, "工资");//    ui->tableView->resizeColumnsToContents(); // 自动调整列宽//    ui->tableView->horizontalHeader()->setStretchLastSection(true); //拉伸最后一列ui->actOpenDB->setEnabled(false);ui->actRecInsert->setEnabled(true);ui->actRecDelete->setEnabled(true);ui->actRecEdit->setEnabled(true);ui->actScan->setEnabled(true);}#include <QFileDialog>void MainWindow::on_actOpenDB_triggered()
{QString fileName = QFileDialog::getOpenFileName(this, "选择数据库","", "SQlite数据库(*.db *.db3)");if(fileName.isEmpty()){return;}DB = QSqlDatabase::addDatabase("QSQLITE");DB.setDatabaseName(fileName);if(!DB.open()){QMessageBox::warning(this, "错误", "打开数据库失败");return;}openTable();}void MainWindow::on_actRecInsert_triggered()
{QSqlQuery query;query.exec("select * from employee where EmpNo = -1");DialogData *dataDlg = new DialogData;Qt::WindowFlags flags = dataDlg->windowFlags();dataDlg->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); //固定大小QSqlRecord curData = query.record();curData.setValue("EmpNo", qryModel->rowCount() + 1000);dataDlg->setInsertRecord(curData);int ret = dataDlg->exec();if(ret == QDialog::Accepted){QSqlRecord recData =  dataDlg->getRecordData();query.prepare("INSERT INTO employee (EmpNo,Name,Gender,Height,Birthday,Mobile,Province,City,Depart,Education,Salary,Memo,Photo) ""VALUES(:EmpNo,:Name,:Gender,:Height,:Birthday,:Mobile,:Province,:City,:Depart,:Education,:Salary,:Memo,:Photo)");query.bindValue(":EmpNo", recData.value("EmpNo"));query.bindValue(":Name", recData.value("Name"));query.bindValue(":Gender", recData.value("Gender"));query.bindValue(":Height", recData.value("Height"));query.bindValue(":Birthday", recData.value("Birthday"));query.bindValue(":Mobile", recData.value("Mobile"));query.bindValue(":Province", recData.value("Province"));query.bindValue(":City", recData.value("City"));query.bindValue(":Depart", recData.value("Depart"));query.bindValue(":Education", recData.value("Education"));query.bindValue(":Salary", recData.value("Salary"));query.bindValue(":Memo", recData.value("Memo"));query.bindValue(":Photo", recData.value("Photo"));if(!query.exec()){QMessageBox::critical(this, "error", "Information:" + query.lastError().text());}else{qryModel->setQuery("SELECT EmpNo,Name,Gender,Height,Birthday,Mobile,Province,City,Depart,Education,Salary From employee order by EmpNo");if(qryModel->lastError().isValid()){QMessageBox::warning(this, "错误", "SqlCmdError" + qryModel->lastError().text());return;}}}delete dataDlg;
}void MainWindow::on_actRecEdit_triggered()
{int curRecNo = theSelection->currentIndex().row();QSqlRecord curRec = qryModel->record(curRecNo);int empNo = curRec.value("EmpNo").toInt();QSqlQuery query;query.prepare("select * from employee where EmpNo = :ID");query.bindValue(":ID", empNo);query.exec();query.first();if(!query.isValid()){return;}curRec = query.record();DialogData *dataDlg = new DialogData;Qt::WindowFlags flags = dataDlg->windowFlags();dataDlg->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); //固定大小dataDlg->setUpdateRecord(curRec);int ret = dataDlg->exec();if(ret == QDialog::Accepted){QSqlRecord recData =  dataDlg->getRecordData();query.prepare("update employee set ""Name=:Name,Gender=:Gender,Height=:Height,Birthday=:Birthday,""Mobile=:Mobile,Province=:Province,City=:City,Depart=:Depart,""Education=:Education,Salary=:Salary,Memo=:Memo,Photo=:Photo where EmpNo=:ID");query.bindValue(":Name", recData.value("Name"));query.bindValue(":Gender", recData.value("Gender"));query.bindValue(":Height", recData.value("Height"));query.bindValue(":Birthday", recData.value("Birthday"));query.bindValue(":Mobile", recData.value("Mobile"));query.bindValue(":Province", recData.value("Province"));query.bindValue(":City", recData.value("City"));query.bindValue(":Depart", recData.value("Depart"));query.bindValue(":Education", recData.value("Education"));query.bindValue(":Salary", recData.value("Salary"));query.bindValue(":Memo", recData.value("Memo"));query.bindValue(":Photo", recData.value("Photo"));query.bindValue(":ID", recData.value("EmpNo"));if(!query.exec()){QMessageBox::critical(this, "error", "Information:" + query.lastError().text());}else{qryModel->setQuery("SELECT EmpNo,Name,Gender,Height,Birthday,Mobile,Province,City,Depart,Education,Salary From employee order by EmpNo");if(qryModel->lastError().isValid()){QMessageBox::warning(this, "错误", "SqlCmdError" + qryModel->lastError().text());return;}}}delete dataDlg;
}void MainWindow::on_actRecDelete_triggered()
{int curRecNo = theSelection->currentIndex().row();QSqlRecord curRec = qryModel->record(curRecNo);int empNo = curRec.value("EmpNo").toInt();QSqlQuery queryDelete;queryDelete.prepare("delete from employee where EmpNo=:ID");queryDelete.bindValue(":ID", empNo);if(!queryDelete.exec()){QMessageBox::warning(this, "错误", "SqlCmdError" + queryDelete.lastError().text());}else{qryModel->setQuery("SELECT EmpNo,Name,Gender,Height,Birthday,Mobile,Province,City,Depart,Education,Salary From employee order by EmpNo");if(qryModel->lastError().isValid()){QMessageBox::warning(this, "错误", "SqlCmdError" + qryModel->lastError().text());return;}}}void MainWindow::on_actScan_triggered()
{QSqlQuery queryEmList;queryEmList.exec("select EmpNo,Salary From employee order by EmpNo");queryEmList.first();QSqlQuery queryUpdate;queryUpdate.prepare("update employee set Salary=:Salary where EmpNo=:ID");while (queryEmList.isValid()){int empID = queryEmList.value("EmpNo").toInt();float salary = queryEmList.value("Salary").toFloat() + 1000;queryUpdate.bindValue(":Salary", salary);queryUpdate.bindValue(":ID", empID);queryUpdate.exec();if(queryUpdate.lastError().isValid()){break;}queryEmList.next();}qryModel->setQuery("SELECT EmpNo,Name,Gender,Height,Birthday,Mobile,Province,City,Depart,Education,Salary From employee order by EmpNo");if(qryModel->lastError().isValid()){QMessageBox::warning(this, "错误", "SqlCmdError" + qryModel->lastError().text());return;}
}void MainWindow::on_TableView_doubleClicked(QModelIndex index)
{Q_UNUSED(index)on_actRecEdit_triggered();
}

在这里插入图片描述

五、QSelRelationalTableModel

QSelRelationalTableModel类为单张的数据库提供了一个可以编辑的数据模型,它支持外键。
QAbstractTableModelQSqlQueryModel //封装了指向SELECT语句从数据库查询数据的功能QSqlTableModelQSqlRelationalTableModel

1、实现程序

在这里插入图片描述

(1)创建项目,基于QMainWindow

在这里插入图片描述

(2)添加图标资源

(3)实现工具栏功能

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);setCentralWidget(ui->tableView);}MainWindow::~MainWindow()
{delete ui;
}#include <QFileDialog>
#include <QMessageBox>
void MainWindow::on_actOpenDB_triggered()
{QString fileName = QFileDialog::getOpenFileName(this, "打开数据库", "","Sqlite数据库(*.db *.db3)");if(fileName.isEmpty()){return;}DB = QSqlDatabase::addDatabase("QSQLITE");DB.setDatabaseName(fileName);if(!DB.open()){QMessageBox::warning(this, "错误", "打开数据库失败");}tabModel = new QSqlRelationalTableModel(this, DB);tabModel->setTable("studInfo");tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);tabModel->setSort(0, Qt::AscendingOrder);tabModel->setHeaderData(0, Qt::Horizontal, "学号");tabModel->setHeaderData(1, Qt::Horizontal, "姓名");tabModel->setHeaderData(2, Qt::Horizontal, "性别");tabModel->setHeaderData(3, Qt::Horizontal, "学院");tabModel->setHeaderData(4, Qt::Horizontal, "专业");tabModel->setRelation(3, QSqlRelation("departments", "departID", "department"));tabModel->setRelation(4, QSqlRelation("majors", "majorID", "major"));theSelection = new QItemSelectionModel(tabModel);ui->tableView->setModel(tabModel);ui->tableView->setSelectionModel(theSelection);// 表格添加代理(学院与专业下拉选)ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView));tabModel->select();ui->actOpenDB->setEnabled(false);ui->actRecAppend->setEnabled(true);ui->actRecInsert->setEnabled(true);ui->actRecDelete->setEnabled(true);ui->actFields->setEnabled(true);}void MainWindow::on_actFields_triggered()
{QSqlRecord emptyRec = tabModel->record();QString str;for (int var = 0; var < emptyRec.count(); ++var){str = str + emptyRec.fieldName(var) + "\n";}QMessageBox::information(this, "字段名称", str);
}void MainWindow::on_actRecAppend_triggered()
{tabModel->insertRow(tabModel->rowCount(), QModelIndex()); // 在末尾添加一条QModelIndex curIndex = tabModel->index(tabModel->rowCount() - 1, 1); //theSelection->clearSelection(); // 清空选择项theSelection->setCurrentIndex(curIndex, QItemSelectionModel::Select); // 设置新的选项ui->actRevert->setEnabled(true);ui->actSubmit->setEnabled(true);
}void MainWindow::on_actRecInsert_triggered()
{QModelIndex curIndex = ui->tableView->currentIndex();tabModel->insertRow(curIndex.row(), QModelIndex()); // 添加一条theSelection->clearSelection(); // 清空选择项theSelection->setCurrentIndex(curIndex, QItemSelectionModel::Select); // 设置新的选项ui->actRevert->setEnabled(true);ui->actSubmit->setEnabled(true);
}void MainWindow::on_actRevert_triggered()
{tabModel->revertAll();ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);
}void MainWindow::on_actSubmit_triggered()
{bool res = tabModel->submitAll();if(!res){QMessageBox::information(this, "信息", "数据保存错误\n" + tabModel->lastError().text(),QMessageBox::Ok, QMessageBox::NoButton);}else{ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);}
}void MainWindow::on_actRecDelete_triggered()
{QModelIndex curIndex = ui->tableView->currentIndex();QModelIndex nextIndex = tabModel->index(curIndex.row() + 1, 0);tabModel->removeRow(curIndex.row()); // 删除theSelection->clearSelection(); // 清空选择项theSelection->setCurrentIndex(nextIndex, QItemSelectionModel::Select); // 设置新的选项ui->actRevert->setEnabled(true);ui->actSubmit->setEnabled(true);
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/700478.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年的AI模型学习/部署/优化

可以的话&#xff0c;github上给点一个小心心&#xff0c;感谢观看。 LDC边缘检测的轻量级密集卷积神经网络&#xff1a; meiqisheng/LDC (github.com)https://github.com/meiqisheng/LDC segment-anything分割一切的图像分割算法模型&#xff1a; meiqisheng/segment-anyt…

群晖NAS DSM7.2.1安装宝塔之后无法登陆账号密码问题解决

宝塔的安装就不在这赘述了&#xff0c;只说下&#xff0c;启动之后默认账号密码无法登陆的问题。 按照上面给出的账号密码&#xff0c;无法登陆 然后点忘记密码&#xff0c;由于是docker安装的&#xff0c;根目录下没有/www/server/panel 。 也没有bt命令 要怎么修改呢。 既然…

【Java程序设计】【C00283】基于Springboot的校园志愿者管理系统(有论文)

基于Springboot的校园志愿者管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的校园志愿者管理系统 本系统分为系统功能模块、管理员功能模块以及志愿者功能模块。 系统功能模块&#xff1a;用户进入到系统…

应用中如何将单数据库升级为集群【数据库集群】【MySQL集群模式】

MySQL集群架构搭建以及多数据源管理实战 应用中如何将单数据库升级为集群1、搭建MySQL集群&#xff0c;实现服务和数据的高可用1>搭建基础MySQL服务。​ 2、启动MySQL服务​ 3、连接MySQL 2>搭建MySQL主从集群1》配置master服务2》配置slave从服务3》主从集群测试4》全库…

Github 2024-02-23 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2024-02-23统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量非开发语言项目4Python项目3TypeScript项目1HTML项目1Dart项目1Rust项目1 从零开始构建你喜爱的技术 创建周…

智胜未来,新时代IT技术人风口攻略-第七版(弃稿)

文章目录 前言鸿蒙生态科普调研人员画像角色先行结论 - 市场下的增量蛋糕高校助力鸿蒙 - 掀起鸿蒙教育热潮高校鸿蒙课程开设占比 - 巨大需求背后是矛盾冲突教研力量并非唯一原因 - 看重教学成果复用与效率 企业布局规划 - 多元市场前瞻视野全盘接纳仍需一段时间 - 积极正向的一…

【新手易错点】golang中byte和rune

1 总体区别 在Golang中&#xff0c;byte和rune是两种不同类型的数据。简单来说&#xff0c;byte是一个8位的无符号整数类型&#xff0c;而rune则是一个32位的Unicode字符类型。 Byte: 在Golang中&#xff0c;byte类型实际上是uint8的别名&#xff0c;它用来表示8位的无符号整…

2.22日学习打卡----正则表达式

2.22日学习打卡 目录&#xff1a; 2.22日学习打卡正则表达式什么是正则表达式&#xff1f;正则表达式的作用正则表达式特点基础语法表格元字符Java 中正则表达式的使用正则表达式语法规则内容限定单个字符限定范围字符限定取反限定 长度限定长度限定符号预定义字符正则表达式的…

【MySQL】MySQL从0到0.9 - 持续更新ing

MySQL SQL 基础 DDL 语句 show databases; show tables; desc table_name; # 获取表信息 show create table 表名; // 查询指定表的建表语句 数据类型 char(10) 不满10个会用空格填充&#xff0c;性能好一点 varchar(10) 变长字符串&#xff0c;性能差一点 CREATE TABLE tabl…

力扣 187. 重复的DNA序列

1.题目 DNA序列 由一系列核苷酸组成&#xff0c;缩写为 A, C, G 和 T.。 例如&#xff0c;"ACGAATTCCG" 是一个 DNA序列 。 在研究 DNA 时&#xff0c;识别 DNA 中的重复序列非常有用。 给定一个表示 DNA序列 的字符串 s &#xff0c;返回所有在 DNA 分子中出现不止一…

【word技巧】word文档如何设置限制编辑

Word文档中为了提高办公效率以及文档安全&#xff0c;我们可以考虑为word文档设置一个限制编辑起到保护文档的作用。今天介绍word文档设置限制编辑的方法。 打开word文档之后&#xff0c;点击功能栏中的【审阅】功能&#xff0c;选择【限制编辑】功能 这是我们勾选右边弹框中的…

【Spring MVC篇】简单案例分析

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Spring MVC】 本专栏旨在分享学习Spring MVC的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、加法计算器二…

匿名+有名管道

管道 相关概念 4种情况 正常情况&#xff0c;如果管道没有数据&#xff0c;读端陷入等待&#xff0c;直到有数据才能唤醒正常情况&#xff0c;如果管道被写满&#xff0c;写端陷入等待&#xff0c;直到有空间才能唤醒写段关闭&#xff0c;读端一直读取&#xff0c;read返回0…

mac m1调试aarch64 android kernel最终方案

问题 这是之前的&#xff0c;调试android kernel的方案还是太笨重了 完美调试android-goldfish(linux kernel) aarch64的方法 然后&#xff0c;看GeekCon AVSS 2023 Qualifier&#xff0c;通过 sdk-repo-linux_aarch64-emulator-8632828.zip 进行启动 完整编译的aosp kernnl…

51单片机学习(4)-----独立按键进一步控制LED灯

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 目录 一. 独立按键灵活控制LED 程序一&#xff1a;单个独立按键控制多个…

Web性能优化-详细讲解与实用方法-MDN文档学习笔记

Web性能优化 查看更多学习笔记&#xff1a;GitHub&#xff1a;LoveEmiliaForever MDN中文官网 性能优良的网站能够提高访问者留存和用户满意度&#xff0c;减少客户端和服务器之间传输的数据量可降低各方的成本 不同的业务目标和用户需求需要不同的性能度量&#xff0c;要提高…

STM32CubeMX FOC工程配置(AuroraFOC)

一. 简介 哈喽&#xff0c;大家好&#xff0c;今天给大家带来基于AuroraFOC开发板的STM32CubeMX的工程配置&#xff0c;主要配置的参数如下: 1. 互补PWM输出 2. 定时器注入中断ADC采样 3. SPI配置 4. USB CDC配置 5. RT Thread配置 大家如果对这几部分感兴趣的话&#xff0c…

贪婪算法入门指南

想象一下&#xff0c;你在玩一款捡金币的游戏。在这个游戏里&#xff0c;地图中散布着各种大小不一的金币&#xff0c;而你的目标就是尽可能快地收集到最多的金币。你可能会采取一个直观的策略&#xff1a;每次都去捡最近的、看起来最大的金币。这种在每一步都采取局部最优解的…

新版Java面试专题视频教程——虚拟机篇①

新版Java面试专题视频教程——虚拟机篇① 1 JVM组成1.1 JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f;1.2 什么是程序计数器&#xff1f;1.3 你能给我详细的介绍Java堆吗?1.3.1 1.7和1.8 堆的区别1.3.2 元空间(MetaSpace)介绍 1.4 什么是虚拟机栈1.4.1 堆和栈的区…

普中51单片机学习(AD转换)

AD转换 分辨率 ADC的分辨率是指使输出数字量变化一个相邻数码所需输入模拟电压的变化量。常用二进制的位数表示。例如12位ADC的分辨率就是12位&#xff0c;或者说分辨率为满刻度的1/(2^12)。 一个10V满刻度的12位ADC能分辨输入电压变化最小值是10V1/(2^12 )2.4mV。 量化误差 …