文章目录
- 1. QSqlQuery基本用法
- 2. QSqlQueryModel和QSqlQuery联合使用
- 2.1 可视化UI设计框架
- 2.1.1主窗口的可视化UI设计框架
- 2.1.2 对话框的可视化UI设计框架
- 2.2 数据表显示
- 2.3 编辑记录对话框
- 2.4 编辑记录
- 2.5 插入记录
- 2.6 删除记录
- 2.7 记录遍历
- 2.8 程序框架及源码
- 2.8.1 程序整体框架
- 2.8.2 源码
1. QSqlQuery基本用法
QSqlQuery 是能执行任意 SQL 语句的类,如 SELECT、INSERT、UPDATE、DELETE 等,QSqlQuery 类的一些常用函数见表 11-11(省略函数中的 const 关键字,省略缺省参数,不同参数的同名函数一般只给出一种参数形式)。
使用 QSqlQuery 执行不带参数的 SQL 语句时可以用 exec(QString)函数,如:
QSqlQuery query;
query.prepare("SELECT * FROM employee where EmpNo=:ID");
query.bindValue(":ID",2003);
query.exec();
上面是SQL语句中的参数用“冒号+参数名”表示的形式,还可以直接用占位符来表示参数,如:
QSqlQuery query;
query.prepare("UPDATE employee SET Name=?, Gender=?, Height=?, where EmpNo=?");
query.bindValue(0,"高某某");
query.bindValue(1,"男");
query.bindValue(2,1.78);
query.bindValue(3,2010);
query.exec();
2. QSqlQueryModel和QSqlQuery联合使用
2.1 可视化UI设计框架
2.1.1主窗口的可视化UI设计框架
2.1.2 对话框的可视化UI设计框架
2.2 数据表显示
QSqlQueryModel 可以查询数据并作为数据模型,实现数据的显示,QSqlQuery 可以执行UPDATE、INSERT、DELETE 等 SQL 语实现数据的编辑修改。
实例samp11_3 通过联合使用QSqlQueryModel和QSqlQuery 组件实现数据表的显示和编辑修改,下图 是实例 samp11_3 运行主窗口。
主窗口类定义如下(去掉有些自动生成部分)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QString>
#include <QtSql>
#include <QDataWidgetMapper>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QSqlDatabase DB; //数据库
QSqlQueryModel *qryModel; //数据库模型
QItemSelectionModel *theSelection; //选择模型
void openTable();//打开数据表
void updateRecord(int recNo); //更新记录
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
这个主窗口类的定义相比于实例samp11_2只是增加了一个updateRecord()函数。工具栏上的“打开数据库”按钮的代码与实例samp11_2 完全相同,会调用openTable()连接数据库并查询数据表的数据。
本实例的openTable()函数代码如下:
void MainWindow::openTable()
{//打开数据表
qryModel=new QSqlQueryModel(this);
theSelection=new QItemSelectionModel(qryModel);
qryModel->setQuery("SELECT empNo, Name, Gender, Height, Birthday, Mobile, Province, City, Department, "
" Education, Salary FROM employee order by empNo");
if (qryModel->lastError().isValid())
{
QMessageBox::information(this, "错误", "数据表查询错误,错误信息\n"+qryModel->lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
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->setModel(qryModel);
ui->tableView->setSelectionModel(theSelection);
// 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);
}
openTable()函数创建了QSqlQueryModel类对象qryModel,从数据表employee 里查询出除了Memo和 Photo 之外的其他字段,并作为界面上的 tableView 的数据模型。还创建了选择模型 theSelection,但是没有为选择模型的currentRowChanged()信号关联槽函数,因为不需要在记录移动时做什么处理。由于使用QSqlQueryModel作为 tableView 的数据源,在 tableView 里是无法编辑修改数据的。
2.3 编辑记录对话框
由于在 tableView 上无法编辑修改数据,只是作为一个只读的数据显示,在主窗口工具栏上提供了“插入记录”“编辑记录”“删除记录”3 个按钮对数据进行编辑。“插入记录”和“编辑记录都会打开一个对话框,编辑一条记录的所有字段数据,确认插入后用 QSqlQuery 执行一条INSERT语句插入一条记录,确认编辑时用 QSqlQuery 执行一个UPDATE 语句更新一条记录。
设计了一个对话框 WDialogData,用于编辑一条记录的所有字段的数据,在“插入记录”和“编辑记录”时调用此对话框,对话框运行界面如下图所示。
WDialogData类的定义如下:
#ifndef WDIALOGDATA_H
#define WDIALOGDATA_H
#include <QDialog>
#include <QSqlRecord>
namespace Ui {
class WDialogData;
}
class WDialogData : public QDialog
{
Q_OBJECT
private:
QSqlRecord mRecord; //保存一条记录的数据
public:
explicit WDialogData(QWidget *parent = 0);
~WDialogData();
void setUpdateRecord(QSqlRecord &recData); //更新记录
void setInsertRecord(QSqlRecord &recData); //插入记录
QSqlRecord getRecordData();//获取录入的数据
private slots:
void on_btnClearPhoto_clicked(); //清理照片
void on_btnSetPhoto_clicked(); //设置照片
private:
Ui::WDialogData *ui;
};
#endif // WDIALOGDATA_H
QSqlRecord 类型的私有变量 mRecord 用于存储一条记录的数据。
插入一条记录时,创建对话框后调用 setInsertRecord()函数初始化对话框的数据;编辑一条记
录时,创建对话框后调用 setUpdateRecord ()函数初始化对话框的数据。
对话框确认修改后,调用getRecordData()时,界面数据存入 mRecord,并将mRecord 作为返回值,返回编辑后的一条记录的数据。
对话框 WDialogData 的所有自定义函数,以及对话框上的“导入照片”“清除照片”按钮的代码如下,程序代码比较简单,这里不再过多解释。
void WDialogData::setUpdateRecord(QSqlRecord &recData)
{ //编辑记录,更新记录数据到界面
mRecord=recData;
ui->spinEmpNo->setEnabled(false); //员工编号不允许编辑
setWindowTitle("更新记录");
//根据recData的数据更新界面显示
ui->spinEmpNo->setValue(recData.value("empNo").toInt());
ui->editName->setText(recData.value("Name").toString());
ui->comboSex->setCurrentText(recData.value("Gender").toString());
ui->spinHeight->setValue(recData.value("Height").toFloat());
ui->editBirth->setDate(recData.value("Birthday").toDate());
ui->editMobile->setText(recData.value("Mobile").toString());
ui->comboProvince->setCurrentText(recData.value("Province").toString());
ui->editCity->setText(recData.value("City").toString());
ui->comboDep->setCurrentText(recData.value("Department").toString());
ui->comboEdu->setCurrentText(recData.value("Education").toString());
ui->spinSalary->setValue(recData.value("Salary").toInt());
ui->editMemo->setPlainText(recData.value("Memo").toString());
QVariant va=recData.value("Photo");//
if (!va.isValid()) //图片字段内容为空
ui->LabPhoto->clear();
else
{
QByteArray data=va.toByteArray();
QPixmap pic;
pic.loadFromData(data);
ui->LabPhoto->setPixmap(pic.scaledToWidth(ui->LabPhoto->size().width()));
}
}
void WDialogData::setInsertRecord(QSqlRecord &recData)
{//插入记录,无需更新界面显示,但是要存储recData的字段结构
mRecord=recData; //保存recData到内部变量
ui->spinEmpNo->setEnabled(true); //插入的记录,员工编号允许编辑
// setWindowTitle("插入新记录");
// ui->spinEmpNo->setValue(recData.value("empNo").toInt());
setWindowTitle("Insert new record");
ui->spinEmpNo->setValue(recData.value("empNo").toInt());
}
QSqlRecord WDialogData::getRecordData()
{ //"确定"按钮后,界面数据保存到记录mRecord
mRecord.setValue("empNo",ui->spinEmpNo->value());
mRecord.setValue("Name",ui->editName->text());
mRecord.setValue("Gender",ui->comboSex->currentText());
mRecord.setValue("Height",ui->spinHeight->value());
mRecord.setValue("Birthday",ui->editBirth->date());
mRecord.setValue("Mobile",ui->editMobile->text());
mRecord.setValue("Province",ui->comboProvince->currentText());
mRecord.setValue("City",ui->editCity->text());
mRecord.setValue("Department",ui->comboDep->currentText());
mRecord.setValue("Education",ui->comboEdu->currentText());
mRecord.setValue("Salary",ui->spinSalary->value());
mRecord.setValue("Memo",ui->editMemo->toPlainText());
//照片编辑时已经修改了mRecord的photo字段的值
return mRecord; //以记录作为返回值
}
2.4 编辑记录
单击主窗口工具栏上的“编辑记录”按钮,或在 tableView 上双击某条记录,会编辑当前记录,代码如下:
void MainWindow::on_actRecEdit_triggered()
{//编辑当前记录
int curRecNo=theSelection->currentIndex().row();
updateRecord(curRecNo);
}
void MainWindow::on_tableView_doubleClicked(const QModelIndex &index)
{ //tableView上双击,编辑当前记录
int curRecNo=index.row();
updateRecord(curRecNo);
}
两个槽函数都会调用 updateRecord()函数,并且以记录的序号作为传递参数。updateRecord()函数实现当前记录的编辑,代码如下:
void MainWindow::updateRecord(int recNo)
{ //更新一条记录
QSqlRecord curRec=qryModel->record(recNo); //获取当前记录
int empNo=curRec.value("EmpNo").toInt();//获取EmpNo
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();//获取当前记录的数据
WDialogData *dataDialog=new WDialogData(this); //创建对话框
Qt::WindowFlags flags=dataDialog->windowFlags();
dataDialog->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); //设置对话框固定大小
dataDialog->setUpdateRecord(curRec);//调用对话框函数更新数据和界面
int ret=dataDialog->exec();// 以模态方式显示对话框
if (ret==QDialog::Accepted) //OK键被按下
{
QSqlRecord recData=dataDialog->getRecordData(); //获得对话框返回的记录
query.prepare("update employee set Name=:Name, Gender=:Gender,Height=:Height,"
" Birthday=:Birthday, Mobile=:Mobile, Province=:Province,"
" City=:City, Department=:Department, 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(":Department",recData.value("Department"));
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",empNo);
if (!query.exec())
QMessageBox::critical(this, "错误", "记录更新错误\n"+query.lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
else
qryModel->query().exec();//数据模型重新查询数据,更新tableView显示
}
delete dataDialog;
}
函数 updateRecord(int recNo)根据行号 reNo 从 qryModel 获取当前记录的 EmpNo 字段的值,即员工编号,然后使用一个QSqlQuery 对象从数据表里查询出这一个员工的所有字段的一条记录。使用 QsqlQuery 时用到了参数 SQL 语句:
query.prepare("select * from employee where EmpNo = :ID");
query.bindValue(":ID",empNo);
query.exec();
由于 EmpNo 是数据表 employee 的主键字段,不允许出现重复,所以只会查询出一条记录,查询出的一条完整记录保存到变量 curRec。
然后创建 WDialogData 类型的对话框 dataDialog,调用 setUpdateRecord(curRec)将完整记录传递给对话框。对话框执行后,如果是“确定”返回,则通过 getRecordData()函数获取对话框编辑后的记录数据:
QSqlRecord recData=dataDialog->getRecordData(); //获得对话框返回的记录
recData 里包含了编辑后的最新数据,然后使用 QSqlQuery 对象执行带参数的 UPDATE 语句更新一条记录。更新成功后,将数据模型 qryModel的SELECT 语句重新执行一次,可刷新 tableView的显示。
2.5 插入记录
工具栏上的”插入记录“可以插入一条新记录,代码如下:
void MainWindow::on_actRecInsert_triggered()
{//插入记录
QSqlQuery query;
query.exec("select * from employee where EmpNo =-1"); //实际不查询出记录,只查询字段信息
QSqlRecord curRec=query.record();//获取当前记录,实际为空记录
curRec.setValue("EmpNo",qryModel->rowCount()+3000);
WDialogData *dataDialog=new WDialogData(this);
Qt::WindowFlags flags=dataDialog->windowFlags();
dataDialog->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); //设置对话框固定大小
dataDialog->setInsertRecord(curRec); //插入记录
int ret=dataDialog->exec();// 以模态方式显示对话框
if (ret==QDialog::Accepted) //OK键被按下
{
QSqlRecord recData=dataDialog->getRecordData();
query.prepare("INSERT INTO employee (EmpNo,Name,Gender,Height,Birthday,Mobile,Province,"
" City,Department,Education,Salary,Memo,Photo) "
" VALUES(:EmpNo,:Name, :Gender,:Height,:Birthday,:Mobile,:Province,"
" :City,:Department,: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(":Department",recData.value("Department"));
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, "错误", "插入记录错误\n"+query.lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
else //插入,删除记录后需要重新设置SQL语句查询
{
QString sqlStr=qryModel->query().executedQuery();// 执行过的SELECT语句
qryModel->setQuery(sqlStr); //重新查询数据
}
}
delete dataDialog;
}
程序首先用QSqlQuery类对象query 执行一个SQL语“select * from employee where EmpNo=-1”这样不会查询到任何记录,目的就是得到一条空记录 curRec。
创建 WDialogData 类型的对话框 dataDialog 后,调用setInsertRecord()函数对话框进行初始化设置。
对话框 dataDialog运行“确认”返回后,使用query 执行INSERT 语插入一条新记录。若插入记录执行成功,需要重新执行数据模型 qryModel 的 SQL 语查询数据,才会更新界面上的tableView 的显示。
2.6 删除记录
工具栏上的“删除记录”删除 tableView 上的当前记录,代码如下:
void MainWindow::on_actRecDelete_triggered()
{//删除当前记录
int curRecNo=theSelection->currentIndex().row();
QSqlRecord curRec=qryModel->record(curRecNo); //获取当前记录
if (curRec.isEmpty()) //当前为空记录
return;
int empNo=curRec.value("EmpNo").toInt();//获取员工编号
QSqlQuery query;
query.prepare("delete from employee where EmpNo = :ID");
query.bindValue(":ID",empNo);
if (!query.exec())
QMessageBox::critical(this, "错误", "删除记录出现错误\n"+query.lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
else //插入,删除记录后需要重新设置SQL语句查询
{
QString sqlStr=qryModel->query().executedQuery();// 执行过的SELECT语句
qryModel->setQuery(sqlStr); //重新查询数据
}
}
从数据模型的当前记录中获取员工编号,然后使用一个 QSqlQuery 类的对象执行一条 DELETE语句删除这条记录。
删除记录后需要重新设置数据模型 qryModel 的SQL语句并查询数据,以更新数据和tableView的显示。
2.7 记录遍历
工具栏上的“涨工资”按钮通过记录遍历,修改所有记录的 Salary 字段的值,其实现代码如下:
void MainWindow::on_actScan_triggered()
{//涨工资,记录遍历
QSqlQuery qryEmpList; //员工工资信息列表
// qryEmpList.setForwardOnly(true);
qryEmpList.exec("SELECT empNo,Salary FROM employee ORDER BY empNo");
qryEmpList.first();
QSqlQuery qryUpdate; //临时 QSqlQuery
qryUpdate.prepare("UPDATE employee SET Salary=:Salary WHERE EmpNo = :ID");
while (qryEmpList.isValid()) //当前记录有效
{
int empID=qryEmpList.value("empNo").toInt(); //获取empNo
float salary=qryEmpList.value("Salary").toFloat(); //获取Salary
salary=salary+1000; //涨工资
qryUpdate.bindValue(":ID",empID);
qryUpdate.bindValue(":Salary",salary); //设置SQL语句参数
qryUpdate.exec(); //执行update
if (!qryEmpList.next()) //移动到下一条记录,并判断是否到末尾了
break;
}
qryModel->query().exec();//数据模型重新查询数据,更新tableView的显示
QMessageBox::information(this, "提示", "涨工资计算完毕",
QMessageBox::Ok,QMessageBox::NoButton);
}
程序里使用了两个 QSqlQuery 类变量,qryEmpList 查询 EmpNo 和 Salary 两个字段的全部记录,qryUpdate 用于执行一个带参数的 UPDATE 语句,每次更新一条记录。
遍历 qryEmpList 的所有记录,QSqlQuery 有 first()、previous()、next()、last()等函数记录移动,若到了最后一条记录后再执行 next(),将返回 false,以此判断是否遍历完所有记录。
2.8 程序框架及源码
2.8.1 程序整体框架
2.8.2 源码
(1)mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QString>
#include <QtSql>
#include <QDataWidgetMapper>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QSqlDatabase DB; //数据库
QSqlQueryModel *qryModel; //数据库模型
QItemSelectionModel *theSelection; //选择模型
void openTable();//打开数据表
void updateRecord(int recNo); //更新记录
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
// QTableView的SelectionModel的行发生了变化,进行处理
// void on_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
///
void on_actOpenDB_triggered();
void on_actRecInsert_triggered();
void on_actRecDelete_triggered();
void on_actRecEdit_triggered();
void on_tableView_doubleClicked(const QModelIndex &index);
void on_actScan_triggered();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
(2)mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include "wdialogdata.h"
void MainWindow::openTable()
{//打开数据表
qryModel=new QSqlQueryModel(this);
theSelection=new QItemSelectionModel(qryModel);
qryModel->setQuery("SELECT empNo, Name, Gender, Height, Birthday, Mobile, Province, City, Department, "
" Education, Salary FROM employee order by empNo");
if (qryModel->lastError().isValid())
{
QMessageBox::information(this, "错误", "数据表查询错误,错误信息\n"+qryModel->lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
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->setModel(qryModel);
ui->tableView->setSelectionModel(theSelection);
// 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);
}
void MainWindow::updateRecord(int recNo)
{ //更新一条记录
QSqlRecord curRec=qryModel->record(recNo); //获取当前记录
int empNo=curRec.value("EmpNo").toInt();//获取EmpNo
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();//获取当前记录的数据
WDialogData *dataDialog=new WDialogData(this); //创建对话框
Qt::WindowFlags flags=dataDialog->windowFlags();
dataDialog->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); //设置对话框固定大小
dataDialog->setUpdateRecord(curRec);//调用对话框函数更新数据和界面
int ret=dataDialog->exec();// 以模态方式显示对话框
if (ret==QDialog::Accepted) //OK键被按下
{
QSqlRecord recData=dataDialog->getRecordData(); //获得对话框返回的记录
query.prepare("update employee set Name=:Name, Gender=:Gender,Height=:Height,"
" Birthday=:Birthday, Mobile=:Mobile, Province=:Province,"
" City=:City, Department=:Department, 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(":Department",recData.value("Department"));
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",empNo);
if (!query.exec())
QMessageBox::critical(this, "错误", "记录更新错误\n"+query.lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
else
qryModel->query().exec();//数据模型重新查询数据,更新tableView显示
}
delete dataDialog;
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setCentralWidget(ui->tableView);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView->setAlternatingRowColors(true);
// ui->tableView->resizeColumnsToContents();
// ui->tableView->horizontalHeader()->setStretchLastSection(true);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actOpenDB_triggered()
{
QString aFile=QFileDialog::getOpenFileName(this,"选择数据库文件","",
"SQL Lite数据库(*.db *.db3)");
if (aFile.isEmpty())
return;
//打开数据库
DB=QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动
DB.setDatabaseName(aFile); //设置数据库名称
// DB.setHostName();
// DB.setUserName();
// DB.setPassword();
if (!DB.open()) //打开数据库
{
QMessageBox::warning(this, "错误", "打开数据库失败",
QMessageBox::Ok,QMessageBox::NoButton);
return;
}
//打开数据表
openTable();
}
void MainWindow::on_actRecInsert_triggered()
{//插入记录
QSqlQuery query;
query.exec("select * from employee where EmpNo =-1"); //实际不查询出记录,只查询字段信息
QSqlRecord curRec=query.record();//获取当前记录,实际为空记录
curRec.setValue("EmpNo",qryModel->rowCount()+3000);
WDialogData *dataDialog=new WDialogData(this);
Qt::WindowFlags flags=dataDialog->windowFlags();
dataDialog->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); //设置对话框固定大小
dataDialog->setInsertRecord(curRec); //插入记录
int ret=dataDialog->exec();// 以模态方式显示对话框
if (ret==QDialog::Accepted) //OK键被按下
{
QSqlRecord recData=dataDialog->getRecordData();
query.prepare("INSERT INTO employee (EmpNo,Name,Gender,Height,Birthday,Mobile,Province,"
" City,Department,Education,Salary,Memo,Photo) "
" VALUES(:EmpNo,:Name, :Gender,:Height,:Birthday,:Mobile,:Province,"
" :City,:Department,: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(":Department",recData.value("Department"));
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, "错误", "插入记录错误\n"+query.lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
else //插入,删除记录后需要重新设置SQL语句查询
{
QString sqlStr=qryModel->query().executedQuery();// 执行过的SELECT语句
qryModel->setQuery(sqlStr); //重新查询数据
}
}
delete dataDialog;
}
void MainWindow::on_actRecDelete_triggered()
{//删除当前记录
int curRecNo=theSelection->currentIndex().row();
QSqlRecord curRec=qryModel->record(curRecNo); //获取当前记录
if (curRec.isEmpty()) //当前为空记录
return;
int empNo=curRec.value("EmpNo").toInt();//获取员工编号
QSqlQuery query;
query.prepare("delete from employee where EmpNo = :ID");
query.bindValue(":ID",empNo);
if (!query.exec())
QMessageBox::critical(this, "错误", "删除记录出现错误\n"+query.lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
else //插入,删除记录后需要重新设置SQL语句查询
{
QString sqlStr=qryModel->query().executedQuery();// 执行过的SELECT语句
qryModel->setQuery(sqlStr); //重新查询数据
}
}
void MainWindow::on_actRecEdit_triggered()
{//编辑当前记录
int curRecNo=theSelection->currentIndex().row();
updateRecord(curRecNo);
}
void MainWindow::on_tableView_doubleClicked(const QModelIndex &index)
{ //tableView上双击,编辑当前记录
int curRecNo=index.row();
updateRecord(curRecNo);
}
void MainWindow::on_actScan_triggered()
{//涨工资,记录遍历
QSqlQuery qryEmpList; //员工工资信息列表
// qryEmpList.setForwardOnly(true);
qryEmpList.exec("SELECT empNo,Salary FROM employee ORDER BY empNo");
qryEmpList.first();
QSqlQuery qryUpdate; //临时 QSqlQuery
qryUpdate.prepare("UPDATE employee SET Salary=:Salary WHERE EmpNo = :ID");
while (qryEmpList.isValid()) //当前记录有效
{
int empID=qryEmpList.value("empNo").toInt(); //获取empNo
float salary=qryEmpList.value("Salary").toFloat(); //获取Salary
salary=salary+1000; //涨工资
qryUpdate.bindValue(":ID",empID);
qryUpdate.bindValue(":Salary",salary); //设置SQL语句参数
qryUpdate.exec(); //执行update
if (!qryEmpList.next()) //移动到下一条记录,并判断是否到末尾了
break;
}
qryModel->query().exec();//数据模型重新查询数据,更新tableView的显示
QMessageBox::information(this, "提示", "涨工资计算完毕",
QMessageBox::Ok,QMessageBox::NoButton);
}
(3)wdialogdata.h
#ifndef WDIALOGDATA_H
#define WDIALOGDATA_H
#include <QDialog>
#include <QSqlRecord>
namespace Ui {
class WDialogData;
}
class WDialogData : public QDialog
{
Q_OBJECT
private:
QSqlRecord mRecord; //保存一条记录的数据
public:
explicit WDialogData(QWidget *parent = 0);
~WDialogData();
void setUpdateRecord(QSqlRecord &recData); //更新记录
void setInsertRecord(QSqlRecord &recData); //插入记录
QSqlRecord getRecordData();//获取录入的数据
private slots:
void on_btnClearPhoto_clicked(); //清理照片
void on_btnSetPhoto_clicked(); //设置照片
private:
Ui::WDialogData *ui;
};
#endif // WDIALOGDATA_H
(4)wdialogdata.cpp
#include "wdialogdata.h"
#include "ui_wdialogdata.h"
#include <QFileDialog>
WDialogData::WDialogData(QWidget *parent) :
QDialog(parent),
ui(new Ui::WDialogData)
{
ui->setupUi(this);
}
WDialogData::~WDialogData()
{
delete ui;
}
void WDialogData::setUpdateRecord(QSqlRecord &recData)
{ //编辑记录,更新记录数据到界面
mRecord=recData;
ui->spinEmpNo->setEnabled(false); //员工编号不允许编辑
setWindowTitle("更新记录");
//根据recData的数据更新界面显示
ui->spinEmpNo->setValue(recData.value("empNo").toInt());
ui->editName->setText(recData.value("Name").toString());
ui->comboSex->setCurrentText(recData.value("Gender").toString());
ui->spinHeight->setValue(recData.value("Height").toFloat());
ui->editBirth->setDate(recData.value("Birthday").toDate());
ui->editMobile->setText(recData.value("Mobile").toString());
ui->comboProvince->setCurrentText(recData.value("Province").toString());
ui->editCity->setText(recData.value("City").toString());
ui->comboDep->setCurrentText(recData.value("Department").toString());
ui->comboEdu->setCurrentText(recData.value("Education").toString());
ui->spinSalary->setValue(recData.value("Salary").toInt());
ui->editMemo->setPlainText(recData.value("Memo").toString());
QVariant va=recData.value("Photo");//
if (!va.isValid()) //图片字段内容为空
ui->LabPhoto->clear();
else
{
QByteArray data=va.toByteArray();
QPixmap pic;
pic.loadFromData(data);
ui->LabPhoto->setPixmap(pic.scaledToWidth(ui->LabPhoto->size().width()));
}
}
void WDialogData::setInsertRecord(QSqlRecord &recData)
{//插入记录,无需更新界面显示,但是要存储recData的字段结构
mRecord=recData; //保存recData到内部变量
ui->spinEmpNo->setEnabled(true); //插入的记录,员工编号允许编辑
// setWindowTitle("插入新记录");
// ui->spinEmpNo->setValue(recData.value("empNo").toInt());
setWindowTitle("Insert new record");
ui->spinEmpNo->setValue(recData.value("empNo").toInt());
}
QSqlRecord WDialogData::getRecordData()
{ //"确定"按钮后,界面数据保存到记录mRecord
mRecord.setValue("empNo",ui->spinEmpNo->value());
mRecord.setValue("Name",ui->editName->text());
mRecord.setValue("Gender",ui->comboSex->currentText());
mRecord.setValue("Height",ui->spinHeight->value());
mRecord.setValue("Birthday",ui->editBirth->date());
mRecord.setValue("Mobile",ui->editMobile->text());
mRecord.setValue("Province",ui->comboProvince->currentText());
mRecord.setValue("City",ui->editCity->text());
mRecord.setValue("Department",ui->comboDep->currentText());
mRecord.setValue("Education",ui->comboEdu->currentText());
mRecord.setValue("Salary",ui->spinSalary->value());
mRecord.setValue("Memo",ui->editMemo->toPlainText());
//照片编辑时已经修改了mRecord的photo字段的值
return mRecord; //以记录作为返回值
}
void WDialogData::on_btnClearPhoto_clicked()
{ //清除照片
ui->LabPhoto->clear();
mRecord.setNull("Photo"); //Photo字段清空
}
void WDialogData::on_btnSetPhoto_clicked()
{//设置照片
QString aFile=QFileDialog::getOpenFileName(this,"选择图片文件","",
"照片(*.jpg)");
if (aFile.isEmpty())
return;
QByteArray data;
QFile* file=new QFile(aFile); //fileName为二进制数据文件名
file->open(QIODevice::ReadOnly);
data = file->readAll();
file->close();
mRecord.setValue("Photo",data); //图片保存到Photo字段
QPixmap pic;
pic.loadFromData(data);
ui->LabPhoto->setPixmap(pic.scaledToWidth(ui->LabPhoto->size().width()));
}