qt QSqlRelationalTableModel 详解

news/2024/11/21 1:26:43/

背景知识:

Qt SQL的API分为不同层:

  1. 驱动层 

 驱动层  对于QT是基于C++来实现的框架,该层主要包括QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorbase、QSqlDriverPlugin and QSqlResult。这一层提供了特定数据库和SQL API层之间的底层桥梁。

  1. SQL API层

SQL API层  对于SQL API 层提供了数据库的访问相关类,其中,QSqlDataBase类进行连接,QSqlQuery完成数据库的交互。除此之外,还有QSqlError、QSqlField、QSqlIndex and QSqlRecord类。

  1. 用户接口层

用户接口层  用户接口层的几个类实现将数据库中的数据链接到窗口部件上,这些类是使用模型/视图框架实现的,他们是更高层次的抽象,主要包括QSqlQureyModel,QSqlTableModel and QSqlRelationalTableModel。

用户接口层的类使用模型/视图框架实现了将数据库中的数据链接到窗口控件上

QTableView是常用的内容显示视图组件。数据模型类有:QSqlQueryModel 、QSqlTableModel 、QSqlRelationalTableModel 

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

QSqlTableModel : 直接设置一个数据表的名称,可以获取数据表的全部记录,结果是可编辑的。

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

QSqlRelationalTableModel

QSqlRelationalTableModel为QSqlTableModel 的子类,为单张的数据库表提供了一个可编辑的数据模型,它支持外键

即将主表里的某个字段存储为代码型字段,而代码的具体意义存储在另外一个数据表里。

主表代码字段和关联数据表的关联通过setRelation函数实现。

//关联函数

virtual void setRelation(int columnconst QSqlRelation &relation);

QSqlRelation(const QString &aTableNameconst QString &indexCol,

               const QString &displayCol)

Column主表的代码字段的序号

QSqlRelation 

aTableName :代码表

indexCol代码字段名称

displayCol代码意义的字段名称

tabModel->setRelation(3,QSqlRelation("departments","departID","department")); //学院   tabModel->setRelation(4,QSqlRelation("majors","majorID","major"));//专业

例子

  1. 数据库使用SQLite数据库,格式为.db3
  2. 模型使用QSqlRelationalTableModel,视图使用QTableView
  3. 因为QSqlRelationalTableModel可编辑,可使用代理处理编辑操作。
  4. 除了关联字段特殊处理外,其他的和QSqlTableModel一样的操作。

打开数据库

void MainWindow::on_actOpenDB_triggered()
{QString aFile=QFileDialog::getOpenFileName(this,"选择数据库文件","","SQL Lite数据库(*.db *.db3)");//    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::openTable()
{//打开数据表tabModel=new QSqlRelationalTableModel(this,DB);tabModel->setTable("studInfo"); //设置数据表tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);  //OnManualSubmit , OnRowChangetabModel->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"));//专业theSelection=new QItemSelectionModel(tabModel);connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));ui->tableView->setModel(tabModel);ui->tableView->setSelectionModel(theSelection);ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView)); //为关系型字段设置缺省代理组件tabModel->select(); //打开数据表//    ui->tableView->resizeColumnsToContents();
//    ui->tableView->horizontalHeader()->setStretchLastSection(true);ui->actOpenDB->setEnabled(false);ui->actRecAppend->setEnabled(true);ui->actRecInsert->setEnabled(true);ui->actRecDelete->setEnabled(true);ui->actFields->setEnabled(true);
}

添加操作

void MainWindow::on_actRecAppend_triggered()
{//添加记录tabModel->insertRow(tabModel->rowCount(),QModelIndex()); //在末尾添加一个记录QModelIndex curIndex=tabModel->index(tabModel->rowCount()-1,1);//创建最后一行的ModelIndextheSelection->clearSelection();//清空选择项theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);/
}

删除

void MainWindow::on_actRecDelete_triggered()
{//删除当前记录tabModel->removeRow(theSelection->currentIndex().row());tabModel->submitAll(); //立即更新
}

保存

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_actRevert_triggered()
{//取消修改tabModel->revertAll();ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);
}


http://www.ppmy.cn/news/605609.html

相关文章

python的print格式化输出,以及使用format来控制。

20210305 time.strftime("%Y%m%d%H%M%S", time.localtime()) 时间格式化 20210206 https://www.runoob.com/w3cnote/python3-print-func-b.html 重点 20210206 https://blog.csdn.net/a19990412/article/details/80149112 !r 20210205 https://www.jianshu.com/p…

LeetCode中等题之使数组中所有元素相等的最小操作数

题目 存在一个长度为 n 的数组 arr &#xff0c;其中 arr[i] (2 * i) 1 &#xff08; 0 < i < n &#xff09;。 一次操作中&#xff0c;你可以选出两个下标&#xff0c;记作 x 和 y &#xff08; 0 < x, y < n &#xff09;并使 arr[x] 减去 1 、arr[y] 加上 1…

Pycharm报错:Process finished with exit code -1073741819 (0xC0000005)

1.本来应该是文件夹目录 写成了文件 2.路径前面没有加r 识别成正则\t,\n等 记录踏坑历程 在用pycharm tensorflow-gpu环境 读tfrecord时出错 pycharm报错&#xff1a;Process finished with exit code -1073741819 (0xC0000005) 。针对这个泛泛的错误&#xff0c;网上存在应对…

LeetCode中等题之两棵二叉搜索树中的所有元素

题目 给你 root1 和 root2 这两棵二叉搜索树。请你返回一个列表&#xff0c;其中包含 两棵树 中的所有整数并按 升序 排序。. 示例 1&#xff1a; 输入&#xff1a;root1 [2,1,4], root2 [1,0,3] 输出&#xff1a;[0,1,1,2,3,4] 示例 2&#xff1a; 输入&#xff1a;root…

查错bug

1.当无法确定引用的母函数的时候,故意制造事故现场引出前面的调用函数

Redis数据类型详解(5基本+3特殊)

目录一、五大基本数据类型1.1、String(字符串)1.2、List(列表)1.3、Set(集合)1.4、Hash(哈希)1.5、Zset(有序集合)二、三种特殊数据类型2.1、geospatial(地理位置)2.1.1、GEOADD2.1.2、GEOPOS2.1.3、GEODIST2.1.4、GEORADIUS2.1.5、GEORADIUSBYMEMBER2.1.6、GEOHASH2.1.7、总结…

LeetCode简单题之1比特与2比特字符

题目 有两种特殊字符&#xff1a; 第一种字符可以用一个比特 0 来表示 第二种字符可以用两个比特(10 或 11)来表示、 给定一个以 0 结尾的二进制数组 bits &#xff0c;如果最后一个字符必须是一位字符&#xff0c;则返回 true 。 示例 1: 输入: bits [1, 0, 0] 输出: true 解…

使virtualenv从您的全局站点包继承特定的包

/ 猿问 使virtualenv从您的全局站点包继承特定的包 Python Bootstrap 冉冉说 2019-08-24 15:01:46 使virtualenv从您的全局站点包继承特定的包我正在寻找一种方法来制作一个virtualenv&#xff0c;其中只包含基本python安装的一些库&#xff08;我选择&#xff09;。更具体一点…