文章目录
关于QSqlDatabase、QSqIRelationalTableModel 、QSqlRecord类的使用可参考:Qt基础 | Qt SQL模块介绍 | Qt SQL模块常用类及其常用函数介绍
一、QSqIRelationalTableModel 的使用
QSqIRelationalTableModel 可以处理关系数据表。所谓关系数据表,是指将主表里的某个字段存储为代码型字段,而代码字段的具体含义是在另一个数据表(代码表)里。QSqIRelationalTableModel 类专门用来编辑这种具有代码字段的数据表,可以很方便地将代码字段与关系数据表建立关系,在显示和编辑数据表时,直接使用关系表的代码意义字典的内容。
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; //数据库连接
QSqlRelationalTableModel *tabModel;//数据模型
QItemSelectionModel *theSelection;//选择模型
void openTable();//打开数据表
// void getFieldNames();//获取字段名称
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_currentChanged(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_actFields_triggered();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
MainWindow 类中定义了几个私有变量:
QSqlDatabase DB
:用于加载数据库驱动和建立与数据库之间的连接QSqlRelationalTableModel *tabModel
:用于指定某个数据表,作为数据表的数据模型,用来编辑关系数据表QItemSelectionModel *theSelection
:作为 tabModel的选择模型
函数:
openTable
:
槽函数:
on_currentChanged
:
2.构造函数
MainWindow 的构造函数代码如下,主要是对 tableView 一些显示属性的设置。
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setCentralWidget(ui->tableView);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView->setAlternatingRowColors(true);
}
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 创建数据模型及其属性设置、选择模型、设置代码字段的查询关系数据表、为关系型字段设置缺省代理组件
使用 QSqIRelationalTableModel 作为指定数据表的数据模型,用于显示与编辑关系数据表,并设置数据模型的属性。
tabModel=new QSqlRelationalTableModel(this,DB);
tabModel->setTable("studInfo"); //设置数据表
tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit); //OnManualSubmit , OnRowChange
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"));//专业
为数据模型创建一个选择模型,当选中的项发生变化时,选择模型发出currentChanged
信号,其关联槽函数用于设置 “保存”和“取消” Action是否可用。
theSelection=new QItemSelectionModel(tabModel);
connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),
this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));
槽函数:
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());
}
为 tableView 设置数据模型与选择模型,为关系型字段设置缺省代理组件
ui->tableView->setModel(tabModel);
ui->tableView->setSelectionModel(theSelection);
ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView)); //为关系型字段设置缺省代理组件
查询数据,并设置一些 Action 的使能状态。
tabModel->select(); //打开数据表
ui->actOpenDB->setEnabled(false);
ui->actRecAppend->setEnabled(true);
ui->actRecInsert->setEnabled(true);
ui->actRecDelete->setEnabled(true);
ui->actFields->setEnabled(true);
4.实际字段代码表
使用 QSqIRelationalTableModel 类设置代码字段的查询关系后,在 tableView 中以代码意义显示代码字段的内容,其实际字段也发生了改变,变成了关系表中的代码意义字段。
void MainWindow::on_actFields_triggered()
{//获取字段列表
QSqlRecord emptyRec=tabModel->record();//获取空记录,只有字段名
QString str;
for (int i=0;i<emptyRec.count();i++)
str=str+emptyRec.fieldName(i)+'\n';
QMessageBox::information(this, "所有字段名", str,
QMessageBox::Ok,QMessageBox::NoButton);
}
5.其他功能–添加、插入、删除、保存、取消
5.1 添加
添加功能是在数据表的末尾添加一行记录,并设置选择模型的索引来选中刚插入的这一行
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);//设置刚插入的行为当前选择行
}
5.2 插入
插入功能是在当前选中行的上一行插入一行,并选中刚插入的这一行。
void MainWindow::on_actRecInsert_triggered()
{//插入记录
QModelIndex curIndex=ui->tableView->currentIndex();
tabModel->insertRow(curIndex.row(),QModelIndex());
theSelection->clearSelection();//清除已有选择
theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);
}
5.3 删除
移除当前行并立即更新到数据库。
void MainWindow::on_actRecDelete_triggered()
{//删除当前记录
tabModel->removeRow(theSelection->currentIndex().row());
tabModel->submitAll(); //立即更新
}
5.4 保存
保存功能即提交所有未更新的修改到数据库。
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);
}
}
5.5 取消
取消功能是取消所有未提交的修改。
void MainWindow::on_actRevert_triggered()
{//取消修改
tabModel->revertAll();
ui->actSubmit->setEnabled(false);
ui->actRevert->setEnabled(false);
}