找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

第26篇 Qt5之数据库(六)SQL关系表格模型QSqlRelationalTableModel

yafeilinux 2017-8-8 00:04 18752人围观 yafeilinux原创

版权声明

该文章原创于Qt开源社区(www.qter.org),作者yafeilinux,转载请注明出处!可以到这里讨论该文章!

导语

       QSqlRelationalTableModel继承自QSqlTableModel,并且对其进行了扩展,提供了对外键的支持。一个外键就是一个表中的一个字段和其他表中的主键字段之间的一对一的映射。例如,student表中的course字段对应的是course表中的id字段,那么就称字段course是一个外键。因为这里的course字段的值是一些数字,这样的显示很不友好,使用关系表格模型,就可以将它显示为course表中的name字段的值。


环境:Windows 7 + Qt 5.8.0(包含QtCreator 4.2.1


正文


一、使用外键

1.新建Qt Widgets应用,名称为relationaltablemodel,基类为QMainWindow类名为MainWindow保持不变。完成后打开relationaltablemodel.pro项目文件,将第一行改为:

  1. QT       += core gui sql
复制代码

       然后保存该文件。

2.下面向项目中添加新的C++头文件connection.h,并更改其内容如下:

  1. #ifndef CONNECTION_H
  2. #define CONNECTION_H
  3. #include <QSqlDatabase>
  4. #include <QSqlQuery>
  5. static bool createConnection()
  6. {
  7.    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
  8.    db.setDatabaseName("database.db");
  9.    if(!db.open()) return false;
  10.    QSqlQuery query;
  11.    query.exec("create table student (id int primarykey, name vchar,course int)");
  12.    query.exec("insert into student values(1,'yafei0',1)");
  13.    query.exec("insert into student values(2,'yafei1',1)");
  14.    query.exec("insert into student values(3,'yafei2',2)");
  15.    
  16.    query.exec("create table course (id int primary key, name vchar, teacher vchar)");
  17.    query.exec("insert into course values(1,'Math','yafeilinux1')");
  18.    query.exec("insert into course values(2,'English','yafeilinux2')");
  19.    query.exec("insert into course values(3,'Computer','yafeilinux3')");
  20.    return true;
  21. }
  22. #endif // CONNECTION_H
复制代码


       在这里建立了两个表,student表中有一字段是course,它是int型的,而course表的主键也是int型的。如果要将course字段和course表进行关联,它们的类型就必须相同,一定要注意这一点。


3.更改main.cpp文件内容如下:
  1. #include "mainwindow.h"
  2. #include <QApplication>
  3. #include "connection.h"

  4. int main(int argc, char *argv[])
  5. {
  6.     QApplication a(argc, argv);
  7.     if(!createConnection()) return 1;
  8.     MainWindow w;
  9.     w.show();
  10.    
  11.     return a.exec();
  12. }
复制代码


4.然后到mainwindow.h文件中,先包含头文件:

  1. #include<QSqlRelationalTableModel>
复制代码

然后添加private类型对象定义:

  1. QSqlRelationalTableModel *model;
复制代码



5.到设计模式,往界面上拖放一个Table View部件。


6.mainwindow.cpp文件中,在构造函数里添加如下代码:

  1. model = new QSqlRelationalTableModel(this);
  2. //字段变化时写入数据库
  3. model->setEditStrategy(QSqlTableModel::OnFieldChange);
  4. model->setTable("student");
  5. //将student表的第三个字段设为course表的id字段的外键,
  6. //并将其显示为course表的name字段的值
  7. model->setRelation(2,QSqlRelation("course","id","name"));
  8. model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
  9. model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
  10. model->setHeaderData(2, Qt::Horizontal, QObject::tr("Course"));
  11. model->select();
  12. ui->tableView->setModel(model);
复制代码



       这里修改了model的提交策略,OnFieldChange表示只要字段被改动就马上写入数据库,这样就不需要我们再执行提交函数了。setRelation()函数实现了创建外键,注意它的格式就行了。


7.运行程序,效果如下图所示。


01.png


       可以看到Course字段已经不再是编号,而是具体的课程名称了。关于外键,大家也应该有一定的认识了吧,说简单点就是将两个相关的表建立一个桥梁,让它们关联起来。


二、使用委托


       有时我们也希望,如果用户更改课程字段,那么只能在课程表中已有的课程中进行选择,而不能随意填写课程。Qt中还提供了一个QSqlRelationalDelegate委托类,它可以为QSqlRelationalTableModel显示和编辑数据。这个委托为一个外键提供了一个QComboBox部件来显示所有可选的数据,这样就显得更加人性化了。使用这个委托很简单,我们先在mainwindow.cpp文件中添加头文件:
  1. #include <QSqlRelationalDelegate>
复制代码

然后继续在构造函数中添加如下一行代码:

  1. ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView));
复制代码



       运行程序,效果如下图所示。

02.png


结语


我们可以根据自己的需要来选择使用哪个模型。如果熟悉SQL语法,又不需要将所有的数据都显示出来,那么只需要使用QSqlQuery就可以了。对于QSqlTableModel,它主要是用来显示一个单独的表格,而QSqlQueryModel可以用来显示任意一个结果集,如果想显示任意一个结果集,而且想使其可读写,那么建议子类化QSqlQueryModel,然后重新实现flags()setData()函数。






31人点赞鲜花

2人点赞握手

2人点赞雷人

路过

鸡蛋

刚表态过的朋友 (35 人)

原作者: yafeilinux

yafeilinux和他的朋友们微信公众号二维码

微信公众号

专注于Qt嵌入式Linux开发等。扫一扫立即关注。

Qt开源社区官方QQ群二维码

QQ交流群

欢迎加入QQ群大家庭,一起讨论学习!


公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了