嵌入式攻城狮_RayJie

嵌入式攻城狮_RayJie

一、QSqlQueryModel 的使用

  使用 QSqlQueryModel 可以从一个数据表或多个数据表里查询数据,只需设计好 SELECT 语句即可。

1.主窗口类定义

#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:
    QLabel  *LabInfo;
    QSqlDatabase  DB; //数据库
    QSqlQueryModel  *qryModel; //数据模型
    QItemSelectionModel *theSelection; //选择模型
    QDataWidgetMapper   *dataMapper;//数据界面映射

    void    openTable();//打开数据表
    void    refreshTableView();//移动记录时刷新TableView的当前行
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:

// QTableView的SelectionModel的行发生了变化,进行处理
    void on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous);

    void on_actOpenDB_triggered();
    void on_actRecFirst_triggered();
    void on_actRecPrevious_triggered();
    void on_actRecNext_triggered();
    void on_actRecLast_triggered();
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

MainWindow 类中定义了几个私有变量:

  • QSqlDatabase DB:用于加载数据库驱动和建立与数据库之间的连接

  • QSqlQueryModel *qryModel:作为数据表的数据模型

  • QItemSelectionModel *theSelection:作为 qryModel 的选择模型,提供 currentChanged()、currentRowChanged()信号,在 qryModel 选择的字段发生变化、当前记录发生变化时发射信号,以便程序进行响应。

    例如,在 currentRowChanged() 信号发射时,设置记录按钮的使能状态,并处理 Photo 字段的查询与照片显示。

  • QDataWidgetMapper *dataMapper:用于实现界面组件与 qryModel 的字段之间的映射。

公有函数:

  • openTable函数用于打开数据库、查询数据、建立界面显示等操作
  • refreshTableView函数用于记录移动后刷新 tableView 上的当前行位置。

槽函数:

  • on_currentRowChanged函数用于在记录移动时,查询出 Memo 和 Photo 字段的内容,并在界面上显示出来。

2.构造函数

  MainWindow 的构造函数代码如下,主要是对 tableView 一些显示属性的设置。

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    LabInfo=new QLabel("记录条数",this);
    LabInfo->setMinimumWidth(200);
    ui->statusBar->addWidget(LabInfo);

    this->setCentralWidget(ui->splitter);

    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableView->setAlternatingRowColors(true);
}
  • setSelectionBehavior函数:用于定义视图(View)选择哪种选择行为

  • setSelectionMode函数:用于定义视图(view)的选择模式

  • setAlternatingRowColors函数:用来控制当前是否启用交替行颜色绘制背景

3.打开数据库

  打开数据库这一部分主要包括:

  • 添加 SQLite 数据库驱动、设置数据库名称、打开数据库
  • 设置数据模型、选择模型、界面组件与模型数据字段间的数据映射

3.1 添加 SQLite 数据库驱动、设置数据库名称、打开数据库

  这一部分主要用到了 QSqlDatabase 类,该类用于处理与数据库的连接。

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();
}

3.2 设置数据模型、选择模型、界面组件与模型数据字段间的数据映射

  使用 QSqlQueryModel 作为数据模型从数据库里查询数据,只需使用 setQuery() 函数设置一个 SELECT 查询语句即可。

qryModel=new QSqlQueryModel(this);
qryModel->setQuery("SELECT empNo, Name, Gender, Height, Birthday, Mobile, Province, City, Department, "
                   " Education, Salary FROM employee ORDER BY empNo");
if (qryModel->lastError().isValid())
{
    QMessageBox::critical(this, "错误", "数据表查询错误,错误信息\n"+qryModel->lastError().text(),
                             QMessageBox::Ok,QMessageBox::NoButton);
    return;
}

  使用 setHeaderData() 函数为每个字段设置显示标题。

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,"工资");

  为 qryModel 创建选择模型 theSelection,并将其 currentRowChanged() 信号与槽函数 on_currentRowChanged() 关联起来。这个槽函数用于在记录移动时,查询除 Memo 和 Photo 字段的内同,并在界面上显示出来。

theSelection=new QItemSelectionModel(qryModel);
//选择行变化时
connect(theSelection,SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
            this,SLOT(on_currentRowChanged(QModelIndex,QModelIndex)));

其对应槽函数为:

void MainWindow::on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{
    Q_UNUSED(previous);
    if (!current.isValid())
    {
        ui->dbLabPhoto->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; //查询当前empNo的Memo和Photo字段的数据
    query.prepare("select EmpNo, Memo, Photo from employee where EmpNo = :ID");
    query.bindValue(":ID",empNo);
    query.exec();
    query.first();

    QVariant    va=query.value("Photo");//
    if (!va.isValid())  //图片字段内容为空
       ui->dbLabPhoto->clear();
    else
    {//显示照片
        QByteArray data=va.toByteArray();
        QPixmap pic;
        pic.loadFromData(data);
        ui->dbLabPhoto->setPixmap(pic.scaledToWidth(ui->dbLabPhoto->size().width()));
    }

    QVariant    va2=query.value("Memo");//显示备注
    ui->dbEditMemo->setPlainText(va2.toString());
}

这个槽函数有 3 个功能:

  • 第一个功能是更新数据映射的行号,使窗口上的字段关联的显示组件刷新显示当前记录的内容。
  • 第二个功能是根据当前行号,判断是否是首记录或尾记录,以更新 4 个记录移动的 Action 的使能状态。
  • 第三个功能是获取当前记录的 EmpNo 字段的值(即员工编号),然后使用 QSqlQuery 执行查询语句 ,只查询出这个员工的 Memo 和 Photo 字段的数据,然后在界面元件上显示。

  接下来,设置 tableView 的数据模型和选择模型,

ui->tableView->setModel(qryModel);
ui->tableView->setSelectionModel(theSelection);

  然后,创建数据界面映射,设置各个界面组件与字段的映射关系。

//创建数据映射
dataMapper= new QDataWidgetMapper();
dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
dataMapper->setModel(qryModel);
dataMapper->addMapping(ui->dbSpinEmpNo,0);//"empNo";
dataMapper->addMapping(ui->dbEditName,1);//"Name";
dataMapper->addMapping(ui->dbComboSex,2);//"Gender";

dataMapper->addMapping(ui->dbSpinHeight,3);//"Height";
dataMapper->addMapping(ui->dbEditBirth,4);//"Birthday";
dataMapper->addMapping(ui->dbEditMobile,5);//"Mobile";

dataMapper->addMapping(ui->dbComboProvince,6);//"Province";
dataMapper->addMapping(ui->dbEditCity,7);//"City";
dataMapper->addMapping(ui->dbComboDep,8);//"Department";

dataMapper->addMapping(ui->dbComboEdu,9);//"Education";
dataMapper->addMapping(ui->dbSpinSalary,10);//"Salary";

dataMapper->toFirst();

4.记录移动

  由于选中行发生变化时,会引起数据模型关联的选择模型发射 currentRowChanged() 信号,在关联的槽函数中会更新数据映射的行号。因此,为数据映射的 QDataWidgetMapper 类设置数据模型后,总是指向数据模型的按当前记录。

void MainWindow::on_actRecFirst_triggered()
{ //首记录
    dataMapper->toFirst();
    refreshTableView();
}

void MainWindow::on_actRecPrevious_triggered()
{ //前一条记录
    dataMapper->toPrevious();
    refreshTableView();
}

void MainWindow::on_actRecNext_triggered()
{//后一条记录
    dataMapper->toNext();
    refreshTableView();
}

void MainWindow::on_actRecLast_triggered()
{//最后一条记录
    dataMapper->toLast();
    refreshTableView();
}

  QDataWidgetMapper 有 4 个函数进行当前记录的移动,分别是 toFirst()、toLast()、toNext() 和 toPrevious() 。使用 QDataWidgetMapper 的记录移动操作后,QDataWidgetMapper 会移动到新纪录上,映射了字段的界面组件会自动显示新记录的字段的数据。但是,tableView 的当前行并不会自动变化,所以需要调用 refreshTableView() 函数刷新 tableView 的显示,其代码为:

void MainWindow::refreshTableView()
{//刷新tableView的当前选择行
    int index=dataMapper->currentIndex();
    QModelIndex curIndex=qryModel->index(index,1);//
    theSelection->clearSelection();//清空选择项
    theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//设置刚插入的行为当前选择行
}

二、QSqlQueryModel 和 QSqlQuery 联合使用

  QSqlQueryModel 可以查询数据并作为数据模型,实现数据的显示,QSqlQuery 可以执行 UPDATE、INSERT、DELETE 等 SQL 语句实现数据的编辑修改。

1.主窗口 MainWindow 类定义

#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 &current, 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

MainWindow 类中定义了几个私有变量:

  • QSqlDatabase DB:用于加载数据库驱动和建立与数据库之间的连接
  • QSqlQueryModel *qryModel:作为数据表的数据模型
  • QItemSelectionModel *theSelection:作为 qryModel 的选择模型

函数:

  • openTable:创建数据模型与选择模型,使用 setQuery() 函数查询数据库中除了 Memo 和 Photo 之外的其他字段内容,设置字段的显示标题,为 tableView 设置数据模型与选择模型,设置一些 Action 的使能状态

  • updateRecord:实现当前记录的编辑并更新到数据库表中。

    步骤包括:

    • 从数据库表中查询除当前员工的所有字段的值
    • 调用对话框更新数据和界面
    • 当 “确认” 键被按下时,获取对话框返回的记录
    • 使用 UPDATE 子句更新一条记录到数据库表中
    • 更新成功后,将数据模型 qryModel 的 SELECT 语句重新执行一次,可刷新 tableView 的显示

2.构造函数

  MainWindow 的构造函数代码如下,主要是对 tableView 一些显示属性的设置。

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);
}
  • setSelectionBehavior函数:用于定义视图(View)选择哪种选择行为

  • setSelectionMode函数:用于定义视图(view)的选择模式

  • setAlternatingRowColors函数:用来控制当前是否启用交替行颜色绘制背景

3.编辑记录对话框

  由于 tableView 上无法编辑修改数据,只是作为一个只读的数据显示。在 ”插入记录” 和 “编辑记录” 都会打开一个对话框,编辑一条记录的所有字段数据,确认插入后用 QSqlQuery 执行一条 INSERT 语句插入一条记录,确认编辑时用 QSqlQuery 执行一个 UPDATE 语句更新一条记录。

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():插入一条记录时,创建对话框后调用 setInsertRecord() 函数初始化对话框的数据
  • setUpdateRecord():编辑一条记录时,创建对话框后调用 setUpdateRecord() 函数初始化对话框的数据
  • getRecordData():对话框确认修改后,调用 getRecordData() 函数,将对话框中的界面组件数据存入 mRecord,并将 mRecord 作为返回值,返回编辑后的一条记录的数据。

槽函数:

  • on_btnClearPhoto_clicked:清除图片显示与清空 记录中的 Photo 字段
  • on_btnSetPhoto_clicked:选择图片,将图片保存到 Photo 字段,重新显示图片

setInsertRecord函数

void WDialogData::setInsertRecord(QSqlRecord &recData)
{//插入记录,无需更新界面显示,但是要存储recData的字段结构
    mRecord=recData; //保存recData到内部变量
    ui->spinEmpNo->setEnabled(true); //插入的记录,员工编号允许编辑
    setWindowTitle("insert a new record");
    ui->spinEmpNo->setValue(recData.value("empNo").toInt());
}

setUpdateRecord函数

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()));
    }
}

getRecordData函数

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()));
}

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() 函数来实现当前记录的编辑并更新到数据库表中。

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;
}

5.插入记录

  首先用 QSqlQuery 类对象 query 执行一行 SQL 语句 select * from employee where EmpNo =-1 ,这样不会查询到任何记录 ,目的就是得到一条空记录;然后设置空记录的主键 EmpNo 字段的值,调用 setInsertRecord() 函数初始化对话框;对话框运行 “确认”返回后,使用query 执行 INSERT 语句插入一条新记录。 若插入记录执行成功,需要重新执行数据模型的查询语句,才会更新界面上的tableView 的显示。

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;
}

6.删除记录

  从数据模型的当前记录中获取员工编号,然后使用 QSqlQuery 类的对象执行一条 DELETE 语句删除这条记录。删除记录后需要重新设置数据模型 qryModel 的 SQL 语句并查询数据,以更新数据和 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);         //重新查询数据
    }
}

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);
}

07-30 03:24