QT的SQL模块 - QSqlTableModel的使用

QT的SQL模块 - QSqlTableModel的使用

QtSQL模块包括多个类,可以实现数据库连接、SQL语句执行、数据获取与界面显示等功能,数据与界面之间使用Model/View架构,从而可以方便地实现数据的界面显示和操作等。

使用SQL模块时,需要在配置文件(.pro)中添加下面这条语句

Qt += sql

在头文件或者源文件中使用Qt SQL模块中的类,要加入以下语句。这样会将Qt SQL模块中的所有类都包含进去。

#include<QtSql>

SQLite数据库的介绍

1、SQLite是一种无需服务器、无需进行任何配置的数据库。

2、SQLite是可以跨平台使用的数据库。

3、SQLite的驱动库文件很小,包含完整功能的驱动可以小到只有500KB。

项目实现前的准备 - 数据表的创建

eployee数据表是一个员工信息表
序号字段名类型描述说明
1EmpNoINT员工编号主键,非空
NameVARCHAR(20)姓名非空
3GenderVARCHAR(4)性别缺省值=“男”
4HeightFLOAT身高缺省值=1.71
5BirthdayDATE出生日期
6MobileVARCHAR(18)手机号
7ProvinceVARCHAR(20)省份
8CityVARCHAR(20)城市
9DepartmentVARCHAR(30)工作部门
10EducationVARCHAR(16)教育程度
11SalaryCURRENCY工资缺省值=3500
12PhotoBLOB照片BLOB字段可存储任何二进制内容
13MemoMEMO备注MEMO字段可存储任意长度普通文本
departments数据表是一个学院信息表
序号字段名类型描述说明
1departIDINT学院编号主键,非空
2departmentsVARCAHR(40)学院名称非空
majors数据表是专业信息表
序号字段名类型描述说明
1majorsIDINT专业编号主键,非空
2majorsVARCAHR(40)专业名称非空
3departIDINT学院编号非空,等于departments表中某个学院的departID
studInfo是一个记录学生信息的数据表
序号字段名类型描述说明
1studIDINT学院编号主键,非空
2nameVARCAHR(10)姓名非空
3genderVARCAHR(4)性别
4departIDINT学院编号非空,departments表中的记录
5majorsIDINT专业编号关联majors表中的记录

Qt SQL模块的主要类介绍

QtSQL提供的主要类的简要功能描述如下图所示

在这里插入图片描述

QSqlDatabase用于建立与数据库的连接,一般先加载需要的数据库驱动,然后设置数据库的登录参数。

数据库的操作一般需要将数据库的内容在界面上进行显示和编辑,Qt采用Model/View结构进行数据库内容的界面显示。QTableModel是常用的数据库内容显示视图组件,用于数据库操作的数据模型类有QSqlQueryModel、QSqlTableModel和QSqlRelationTableModel他们的继承关系如下图所示。

在这里插入图片描述

QSqlQueryModel通过设置SELECT语句查询获取数据库的内容,但是QSqlQueryModel的数据是只读的,不能进行编辑。

QSqlTableModel直接设置一个数据表的名称,可以获取数据表的全部记录,其结果是可编辑的,设置为界面上的QTableView组件的数据模型后就可以显示和编辑了。

QSqlRelationTableModel编辑一个数据表,并将代码字段通过关系与代码表进行关联,将代码字段的编辑转换为直观的内容选择编辑

QSqlQuery是另外一个经常使用的类,可以执行任何SQL语句,特别是没有返回记录的语句,如UPDATA、INSERT、DELETE等,通过SQL语句对数据库直接进行编辑修改。

QSQqlTableModel的项目实现

实现功能

使用QSQqlTableModel显示数据库demodb中employ数据表的内容,实现了编辑、插入、删除记录的操作。实现数据的排序和记录过滤,还实现了BLOB类型字段photo中存储照片的显示、导入等操作。

运行界面如下

在这里插入图片描述

对MainWindow类中私有变量的介绍

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

QSqlTableModel *tabModel,用于指定某一个 数据表,作为数据表的数据模型

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

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

QWComboBoxDelegate 是自定义的基于QComboBox的代理类,delegateSex和delegateDepart用作tableView中的“性别”和”部门“字段的代理组件。

代码实现

mainwindow.h的实现

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include    <QMainWindow>
#include    <QLabel>
#include    <QString>
#include    <QtSql>
#include    <QDataWidgetMapper>

#include    "qwcomboboxdelegate.h"

namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QSqlDatabase  DB;//数据库连接
    QSqlTableModel  *tabModel;  //数据模型
    QItemSelectionModel *theSelection; //选择模型
    QDataWidgetMapper   *dataMapper; //数据映射

    QWComboBoxDelegate   delegateSex; //自定义数据代理,性别
    QWComboBoxDelegate   delegateDepart; //自定义数据代理,部门

    void    openTable();//打开数据表
    void    getFieldNames();//获取字段名称,填充“排序字段”的comboBox
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

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

    void on_actOpenDB_triggered();
    void on_actRecAppend_triggered();
    void on_actRecInsert_triggered();
    void on_actRevert_triggered();
    void on_actSubmit_triggered();
    void on_actRecDelete_triggered();
    void on_actPhoto_triggered();
    void on_actPhotoClear_triggered();
    void on_radioBtnAscend_clicked();
    void on_radioBtnDescend_clicked();
    void on_radioBtnMan_clicked();
    void on_radioBtnWoman_clicked();
    void on_radioBtnBoth_clicked();
    void on_comboFields_currentIndexChanged(int index);
    void on_actScan_triggered();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp的实现

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include    <QFileDialog>
#include    <QMessageBox>

void MainWindow::openTable()
{//打开数据表
    tabModel=new QSqlTableModel(this,DB);//数据表
    tabModel->setTable("employee"); //设置数据表
    //数据保存方式,OnManualSubmit , OnRowChange
    tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
    tabModel->setSort(tabModel->fieldIndex("empNo"),Qt::AscendingOrder); //排序
    if (!(tabModel->select()))//查询数据
    {
        QMessageBox::critical(this, "错误信息",
                              "打开数据表错误,错误信息\n"+tabModel->lastError().text(),
                              QMessageBox::Ok,QMessageBox::NoButton);
        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("Department"),Qt::Horizontal,"部门");
    tabModel->setHeaderData(tabModel->fieldIndex("Education"),Qt::Horizontal,"学历");
    tabModel->setHeaderData(tabModel->fieldIndex("Salary"),Qt::Horizontal,"工资");

    //这两个字段不再tableView中显示   ???
    //    ui->tableView->setColumnHidden(tabModel->fieldIndex("Memo"),true);//隐藏列
    //    ui->tableView->setColumnHidden(tabModel->fieldIndex("Photo"),true);//隐藏列
    tabModel->setHeaderData(tabModel->fieldIndex("Memo"),Qt::Horizontal,"备注");
    tabModel->setHeaderData(tabModel->fieldIndex("Photo"),Qt::Horizontal,"照片");

    theSelection=new QItemSelectionModel(tabModel);//关联选择模型
    //theSelection当前项变化时触发currentChanged信号
    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->setModel(tabModel);//设置数据模型
    ui->tableView->setSelectionModel(theSelection); //设置选择模型
    ui->tableView->setColumnHidden(tabModel->fieldIndex("Memo"),true);//隐藏列
    ui->tableView->setColumnHidden(tabModel->fieldIndex("Photo"),true);//隐藏列

    //tableView上为“性别”和“部门”两个字段设置自定义代理组件
    QStringList strList;
    strList<<"男"<<"女";
    bool isEditable=false;
    delegateSex.setItems(strList,isEditable);
    //找到性别的这一列,设置其属性
    ui->tableView->setItemDelegateForColumn(
                tabModel->fieldIndex("Gender"),&delegateSex); //Combbox选择型

    strList.clear();
    strList<<"销售部"<<"技术部"<<"生产部"<<"行政部";
    isEditable=true;
    delegateDepart.setItems(strList,isEditable);
    ui->tableView->setItemDelegateForColumn(tabModel->fieldIndex("Department"),
                                            &delegateDepart); //Combbox选择型

    //创建界面组件与数据模型的字段之间的数据映射
    dataMapper= new QDataWidgetMapper();
    dataMapper->setModel(tabModel);//设置数据模型
    dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);//

    //    dataMapper->setItemDelegate(new QSqlRelationalDelegate(this)); //含有外键的
    //界面组件与tabModel的具体字段之间的联系
    // 工号  姓名  性别  身高  出生日期  手机号  出生省份  城市  部门  学历  工资 备注
    //tabModel->fieldIndex() -> 根据字段名称返回其在模型中的字段序号,若字段不存在返回-1
    dataMapper->addMapping(ui->dbSpinEmpNo,tabModel->fieldIndex("empNo"));
    dataMapper->addMapping(ui->dbEditName,tabModel->fieldIndex("Name"));
    dataMapper->addMapping(ui->dbComboSex,tabModel->fieldIndex("Gender"));

    dataMapper->addMapping(ui->dbSpinHeight,tabModel->fieldIndex("Height"));
    dataMapper->addMapping(ui->dbEditBirth,tabModel->fieldIndex("Birthday"));
    dataMapper->addMapping(ui->dbEditMobile,tabModel->fieldIndex("Mobile"));

    dataMapper->addMapping(ui->dbComboProvince,tabModel->fieldIndex("Province"));
    dataMapper->addMapping(ui->dbEditCity,tabModel->fieldIndex("City"));
    dataMapper->addMapping(ui->dbComboDep,tabModel->fieldIndex("Department"));

    dataMapper->addMapping(ui->dbComboEdu,tabModel->fieldIndex("Education"));
    dataMapper->addMapping(ui->dbSpinSalary,tabModel->fieldIndex("Salary"));

    dataMapper->addMapping(ui->dbEditMemo,tabModel->fieldIndex("Memo"));

    //    dataMapper->addMapping(ui->dbPhoto,tabModel->fieldIndex("Photo")); //图片无法直接映射

    dataMapper->toFirst();//移动到首记录

    getFieldNames();//获取字段名称列表,填充ui->groupBoxSort组件

    //更新actions和界面组件的使能状态
    ui->actOpenDB->setEnabled(false);

    ui->actRecAppend->setEnabled(true);
    ui->actRecInsert->setEnabled(true);
    ui->actRecDelete->setEnabled(true);
    ui->actScan->setEnabled(true);

    ui->groupBoxSort->setEnabled(true);
    ui->groupBoxFilter->setEnabled(true);
}

void MainWindow::getFieldNames()
{ //获取所有字段名称
    QSqlRecord  emptyRec=tabModel->record();//获取空记录,只有字段名
    for (int i=0;i<emptyRec.count();i++)
        ui->comboFields->addItem(emptyRec.fieldName(i));
}

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

    this->setCentralWidget(ui->splitter);

    //   tableView显示属性设置
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
    ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableView->setAlternatingRowColors(true);
    //    ui->tableView->resizeColumnsToContents();
    //    ui->tableView->horizontalHeader()->setStretchLastSection(true);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_currentChanged(const QModelIndex &current, const QModelIndex &previous)
{//更新actPost和actCancel 的状态  当表格发生变化时
    Q_UNUSED(current);
    Q_UNUSED(previous);
    ui->actSubmit->setEnabled(tabModel->isDirty()); //有未保存修改时可用
    ui->actRevert->setEnabled(tabModel->isDirty());
}

void MainWindow::on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{//当行发生变化时
    Q_UNUSED(previous);
    // 行切换时的状态控制
    ui->actRecDelete->setEnabled(current.isValid());
    ui->actPhoto->setEnabled(current.isValid());
    ui->actPhotoClear->setEnabled(current.isValid());

    if (!current.isValid())
    {
        ui->dbLabPhoto->clear(); //清除图片显示
        return;
    }

    dataMapper->setCurrentIndex(current.row()); //更新数据映射的行号

    int curRecNo=current.row();//获取行号
    QSqlRecord  curRec=tabModel->record(curRecNo); //获取当前记录

    if (curRec.isNull("Photo"))  //图片字段内容为空
        ui->dbLabPhoto->clear();
    else
    {
        QByteArray data=curRec.value("Photo").toByteArray();
        QPixmap pic;
        pic.loadFromData(data);
        ui->dbLabPhoto->setPixmap(pic.scaledToWidth(ui->dbLabPhoto->size().width()));
    }
}

void MainWindow::on_actOpenDB_triggered()
{//打开数据表
    QString aFile=QFileDialog::getOpenFileName(this,"选择数据库文件","",
                                               "SQL Lite数据库(*.db *.db3)");
    if (aFile.isEmpty())  //选择SQL Lite数据库文件
        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_actRecAppend_triggered()
{//添加记录
    tabModel->insertRow(tabModel->rowCount(),QModelIndex()); //在末尾添加一个记录

    QModelIndex curIndex=tabModel->index(tabModel->rowCount()-1,1);//创建最后一行的ModelIndex
    theSelection->clearSelection();//清空选择项
    theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//设置刚插入的行为当前选择行

    int currow=curIndex.row(); //获得当前行
    tabModel->setData(tabModel->index(currow,0),2000+tabModel->rowCount()); //自动生成编号
    tabModel->setData(tabModel->index(currow,2),"男");
    // 插入行时设置缺省值,需要在primeInsert()信号里去处理
}

void MainWindow::on_actRecInsert_triggered()
{//插入记录
    QModelIndex curIndex=ui->tableView->currentIndex();

    tabModel->insertRow(curIndex.row(),QModelIndex());

    theSelection->clearSelection();//清除已有选择
    theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);
}

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=theSelection->currentIndex();//获取当前选择单元格的模型索引
    tabModel->removeRow(curIndex.row()); //删除最后一行
}

void MainWindow::on_actPhoto_triggered()
{
    //设置照片
    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();

    int curRecNo=theSelection->currentIndex().row();
    QSqlRecord  curRec=tabModel->record(curRecNo); //获取当前记录
    curRec.setValue("Photo",data); //设置字段数据
    tabModel->setRecord(curRecNo,curRec);

    QPixmap pic;
    pic.load(aFile);  //在界面上显示
    ui->dbLabPhoto->setPixmap(pic.scaledToWidth(ui->dbLabPhoto->width()));
}

void MainWindow::on_actPhotoClear_triggered()
{
    int curRecNo=theSelection->currentIndex().row();
    QSqlRecord  curRec=tabModel->record(curRecNo); //获取当前记录

    curRec.setNull("Photo");//设置为空值
    tabModel->setRecord(curRecNo,curRec);

    ui->dbLabPhoto->clear();
}

void MainWindow::on_radioBtnAscend_clicked()
{//升序
    tabModel->setSort(ui->comboFields->currentIndex(),Qt::AscendingOrder);
    tabModel->select();
}

void MainWindow::on_radioBtnDescend_clicked()
{//降序
    tabModel->setSort(ui->comboFields->currentIndex(),Qt::DescendingOrder);
    tabModel->select();
}

void MainWindow::on_radioBtnMan_clicked()
{
    tabModel->setFilter(" Gender='男' ");
    //    tabModel->select();
}

void MainWindow::on_radioBtnWoman_clicked()
{
    tabModel->setFilter(" Gender='女' ");
    //    tabModel->select();
}

void MainWindow::on_radioBtnBoth_clicked()
{
    tabModel->setFilter("");
}

void MainWindow::on_comboFields_currentIndexChanged(int index)
{//选择字段进行排序
    if (ui->radioBtnAscend->isChecked())
        tabModel->setSort(index,Qt::AscendingOrder);
    else
        tabModel->setSort(index,Qt::DescendingOrder);

    tabModel->select();
}

void MainWindow::on_actScan_triggered()
{//涨工资,记录遍历
    if (tabModel->rowCount()==0)
        return;
    for (int i=0;i<tabModel->rowCount();i++)
    {
        QSqlRecord aRec=tabModel->record(i); //获取当前记录
        float salary=aRec.value("Salary").toFloat();
        salary=salary*1.1;
        aRec.setValue("Salary",salary);
        tabModel->setRecord(i,aRec);
    }

    // 索引方式刷新记录,速度一样
    //    float   salary;
    //    for (int i=0;i<tabModel->rowCount();i++)
    //    {
    //        salary=tabModel->data(tabModel->index(i,10)).toFloat();
    //        salary=salary*1.1;
    //        tabModel->setData(tabModel->index(i,10),salary);
    //    }

    if (tabModel->submitAll())
        QMessageBox::information(this, "消息", "涨工资计算完毕",
                                 QMessageBox::Ok,QMessageBox::NoButton);
}

qwcomboboxdelegate.h的实现

#ifndef QWCOMBOBOXDELEGATE_H
#define QWCOMBOBOXDELEGATE_H

#include    <QStyledItemDelegate>
#include    <QComboBox>

class QWComboBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT

private:
    QStringList m_ItemList;//选择列表
    bool    m_isEdit; //是否可编辑

public:
    QWComboBoxDelegate(QObject *parent=0);

    void    setItems(QStringList items, bool isEdit);//初始化设置列表内容,是否可编辑
    //自定义代理组件必须继承以下4个函数
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const Q_DECL_OVERRIDE;

    void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const Q_DECL_OVERRIDE;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                              const QModelIndex &index) const Q_DECL_OVERRIDE;
};

#endif // QWCOMBOBOXDELEGATE_H

qwcomboboxdelegate.cpp的实现

#include "qwcomboboxdelegate.h"
#include    <QComboBox>

QWComboBoxDelegate::QWComboBoxDelegate(QObject *parent):QStyledItemDelegate(parent)
{
}

void QWComboBoxDelegate::setItems(QStringList items, bool isEdit)
{
    m_ItemList=items;
    m_isEdit=isEdit;
}

QWidget *QWComboBoxDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option,
											const QModelIndex &index) const
{
    Q_UNUSED(option);
    Q_UNUSED(index);

    QComboBox *editor = new QComboBox(parent);
    for (int i=0;i<m_ItemList.count();i++)   //从字符串列表初始下拉列表
        editor->addItem(m_ItemList.at(i));

    editor->setEditable(m_isEdit); //是否可编辑
    return editor;
}

void QWComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QString str = index.model()->data(index, Qt::EditRole).toString();

    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    comboBox->setCurrentText(str);
}

void QWComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, 
										const QModelIndex &index) const
{
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    QString str = comboBox->currentText();
    model->setData(index, str, Qt::EditRole);
}

void QWComboBoxDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,
												const QModelIndex &index) const
{
    Q_UNUSED(index);
    editor->setGeometry(option.rect);
}

打开数据表

工具栏上的“打开”按钮有actOpenDB生成,单击按钮时将添加SQLite数据库驱动、打开数据库文件、连接employee数据表并设置显示熟悉,并且创建tableView显示的代理组件,设置数据源与界面组件的映射等,响应代码如下

void MainWindow::on_actOpenDB_triggered()
{//打开数据表
    QString aFile=QFileDialog::getOpenFileName(this,"选择数据库文件","",
                                               "SQL Lite数据库(*.db *.db3)");
    if (aFile.isEmpty())  //选择SQL Lite数据库文件
        return;

    //打开数据库
    DB=QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动  什么类型的数据库

    DB.setDatabaseName(aFile); //设置数据库名称
    if (!DB.open())   //打开数据库
    {
        QMessageBox::warning(this, "错误", "打开数据库失败",
                             QMessageBox::Ok,QMessageBox::NoButton);
        return;
    }
    //打开数据表  使得数据显示到界面上
    openTable();
}

私有变量DB时QSqlDatabase类。QSqlDatabase用于数据库的操作,包括建立数据库连接,设置登录数据库的参数,打开数据库等。下面一行语句使用QSqlDatabase的静态函数addDatabase()添加SQLite数据库的驱动

DB=QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动  什么类型的数据库
openTable()函数

主要创建QSqlTableModel类型的私有变量tabModel,指定需要打开的数据表为employee,设置与界面显示组件的关联等。QSqlTableModel设置一个数据表名称后,作为数据表的数据模型,可以方便地编辑一个数据表。使用的核心类时QSqlTableModel,其主要函数功能如下图所示。

在这里插入图片描述

表示记录的类QSqlRecord

QSqlRecord类记录了数据表的字段信息和一条记录的数据内容,QSqlRecord封装了对记录的字段定义和数据的操作,其主要函数功能如下图所示。

在这里插入图片描述

QSqlRecord用于字段操作的函数一般有两种参数形式的同名函数,用于字段序号或字段名表示一个字段,如value()函数返回一个字段的值,有如下两种形式的函数:

​ QVariant value(int index),返回序号为index的字段的值

​ QVariant value(QString &name),返回字段名称为name的字段的值

表示字段的类QSqlField

QSqlRecord的field()函数返回某个字段,返回数据类型是QSqlField,QSqlField封装了字段定义信息和数据,字段的定义一般在设计数据表时就固定了,不用在QSqlField里修改。QSqlField用于字段数据读写的主要函数功能下下图所示。

在这里插入图片描述

tableView的设置

界面上用一个QTableView组件显示tabModel的表格数据内容,设置其数据模型和选择模型,并且将Memo和Photo两个字段的列设置为隐藏,因为在表格里难以显示备注文字和图片。

数据映射

QDataWidgetMapper用于建立界面组件与数据模型之间的映射,可以将界面的QLineEdit、QCombobox等组件与数据模型的一个字段关联起来。

创建QDataWidgetMapper类的变量dataMapper后,用setModel()设置关联的数据模型,setSubmitPolicy()函数设置数据提交策略,有自动和手动两种方式,addMapping()用于设置界面组件与数据模型列的映射,程序在界面上的各编辑组件与数据表的各字段之间建立了映射关系。Memo字段可以与一个QPlainTextEdit的组件映射,但是Photo时一个BLOB字段没有租价你可以直接显示其内容。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值