QtSQL模块包括多个类,可以实现数据库连接、SQL语句执行、数据获取与界面显示等功能,数据与界面之间使用Model/View架构,从而可以方便地实现数据的界面显示和操作等。
使用SQL模块时,需要在配置文件(.pro)中添加下面这条语句
Qt += sql
在头文件或者源文件中使用Qt SQL模块中的类,要加入以下语句。这样会将Qt SQL模块中的所有类都包含进去。
#include
1、SQLite是一种无需服务器、无需进行任何配置的数据库。
2、SQLite是可以跨平台使用的数据库。
3、SQLite的驱动库文件很小,包含完整功能的驱动可以小到只有500KB。
序号 | 字段名 | 类型 | 描述 | 说明 |
---|---|---|---|---|
1 | EmpNo | INT | 员工编号 | 主键,非空 |
2 | Name | VARCHAR(20) | 姓名 | 非空 |
3 | Gender | VARCHAR(4) | 性别 | 缺省值=“男” |
4 | Height | FLOAT | 身高 | 缺省值=1.71 |
5 | Birthday | DATE | 出生日期 | |
6 | Mobile | VARCHAR(18) | 手机号 | |
7 | Province | VARCHAR(20) | 省份 | |
8 | City | VARCHAR(20) | 城市 | |
9 | Department | VARCHAR(30) | 工作部门 | |
10 | Education | VARCHAR(16) | 教育程度 | |
11 | Salary | CURRENCY | 工资 | 缺省值=3500 |
12 | Photo | BLOB | 照片 | BLOB字段可存储任何二进制内容 |
13 | Memo | MEMO | 备注 | MEMO字段可存储任意长度普通文本 |
序号 | 字段名 | 类型 | 描述 | 说明 |
---|---|---|---|---|
1 | departID | INT | 学院编号 | 主键,非空 |
2 | departments | VARCAHR(40) | 学院名称 | 非空 |
序号 | 字段名 | 类型 | 描述 | 说明 |
---|---|---|---|---|
1 | majorsID | INT | 专业编号 | 主键,非空 |
2 | majors | VARCAHR(40) | 专业名称 | 非空 |
3 | departID | INT | 学院编号 | 非空,等于departments表中某个学院的departID |
序号 | 字段名 | 类型 | 描述 | 说明 |
---|---|---|---|---|
1 | studID | INT | 学院编号 | 主键,非空 |
2 | name | VARCAHR(10) | 姓名 | 非空 |
3 | gender | VARCAHR(4) | 性别 | |
4 | departID | INT | 学院编号 | 非空,departments表中的记录 |
5 | majorsID | INT | 专业编号 | 关联majors表中的记录 |
QtSQL提供的主要类的简要功能描述如下图所示
QSqlDatabase用于建立与数据库的连接,一般先加载需要的数据库驱动,然后设置数据库的登录参数。
数据库的操作一般需要将数据库的内容在界面上进行显示和编辑,Qt采用Model/View结构进行数据库内容的界面显示。QTableModel是常用的数据库内容显示视图组件,用于数据库操作的数据模型类有QSqlQueryModel、QSqlTableModel和QSqlRelationTableModel他们的继承关系如下图所示。
QSqlQueryModel通过设置SELECT语句查询获取数据库的内容,但是QSqlQueryModel的数据是只读的,不能进行编辑。
QSqlTableModel直接设置一个数据表的名称,可以获取数据表的全部记录,其结果是可编辑的,设置为界面上的QTableView组件的数据模型后就可以显示和编辑了。
QSqlRelationTableModel编辑一个数据表,并将代码字段通过关系与代码表进行关联,将代码字段的编辑转换为直观的内容选择编辑
QSqlQuery是另外一个经常使用的类,可以执行任何SQL语句,特别是没有返回记录的语句,如UPDATA、INSERT、DELETE等,通过SQL语句对数据库直接进行编辑修改。
使用QSQqlTableModel显示数据库demodb中employ数据表的内容,实现了编辑、插入、删除记录的操作。实现数据的排序和记录过滤,还实现了BLOB类型字段photo中存储照片的显示、导入等操作。
运行界面如下
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
#include
#include
#include
#include
#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 ¤t, const QModelIndex &previous);
// QTableView的SelectionModel的行发生了变化,进行处理
void on_currentRowChanged(const QModelIndex ¤t, 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
#include
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;icomboFields->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 ¤t, 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 ¤t, 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;irowCount();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;irowCount();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
#include
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
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;iaddItem(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(editor);
comboBox->setCurrentText(str);
}
void QWComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QComboBox *comboBox = static_cast(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数据库驱动 什么类型的数据库
主要创建QSqlTableModel类型的私有变量tabModel,指定需要打开的数据表为employee,设置与界面显示组件的关联等。QSqlTableModel设置一个数据表名称后,作为数据表的数据模型,可以方便地编辑一个数据表。使用的核心类时QSqlTableModel,其主要函数功能如下图所示。
QSqlRecord类记录了数据表的字段信息和一条记录的数据内容,QSqlRecord封装了对记录的字段定义和数据的操作,其主要函数功能如下图所示。
QSqlRecord用于字段操作的函数一般有两种参数形式的同名函数,用于字段序号或字段名表示一个字段,如value()函数返回一个字段的值,有如下两种形式的函数:
QVariant value(int index),返回序号为index的字段的值
QVariant value(QString &name),返回字段名称为name的字段的值
QSqlRecord的field()函数返回某个字段,返回数据类型是QSqlField,QSqlField封装了字段定义信息和数据,字段的定义一般在设计数据表时就固定了,不用在QSqlField里修改。QSqlField用于字段数据读写的主要函数功能下下图所示。
界面上用一个QTableView组件显示tabModel的表格数据内容,设置其数据模型和选择模型,并且将Memo和Photo两个字段的列设置为隐藏,因为在表格里难以显示备注文字和图片。
QDataWidgetMapper用于建立界面组件与数据模型之间的映射,可以将界面的QLineEdit、QCombobox等组件与数据模型的一个字段关联起来。
创建QDataWidgetMapper类的变量dataMapper后,用setModel()设置关联的数据模型,setSubmitPolicy()函数设置数据提交策略,有自动和手动两种方式,addMapping()用于设置界面组件与数据模型列的映射,程序在界面上的各编辑组件与数据表的各字段之间建立了映射关系。Memo字段可以与一个QPlainTextEdit的组件映射,但是Photo时一个BLOB字段没有租价你可以直接显示其内容。