Qt数据库

一、Qt SQL模块概述
1、Qt SQL模块提供数据库编程的支持。

2、Qt支持多种常见的数据库,提供这些数据库的驱动。
  驱动名      数据库
  QDB2       IBM DB2 (version 7.1 and above)
  QMYSQL     MySQL
  QOCI       Oracle Call Interface Driver (version 12.1 and above)
  QODBC      Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases
  QPSQL      PostgreSQL (versions 7.3 and above)
  QSQLITE    SQLite version 3
  
3、Qt SQL模块包括多个类,分为不同的层:
  (1)、驱动层
      主要包括QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorBase、QSqlDriverPlugin、QSqlResult等,这一层提供了特定数据库和SQL API层之间的底层桥梁。
  (2)、SQL API层
      主要提供了数据库的访问相关类,QSqlDatabase类进行连接,QSqlQuery类与数据库交互,还有QSqlError、QSqlField、QSqlIndex、QSqlRecord类等。
  (3)、用户接口层
      实现将数据库中的数据链接到窗口部件上,这些类使用模型Model/视图View框架,主要包括QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel类等。

4、在项目中进行数据库编程的流程:
  (1)、在项目配置文件.pro中增加语句 Qt += sql。
  (2)、在头文件或源文件中增加包含语句 #include
      此句会将Qt SQL模块中的所有类都包含进去; 若只使用其中某些类,为避免冗余可以单独包含某个类。
  (3)、查看Qt对数据库类型的支持。
      QStringList drivers = QSqlDatabase::drivers();
      foreach (QString driver, drivers)
      {
          qDebug() << driver;
      }
  (4)、连接与打开数据库。
      //该类对象就相当于一个数据库,所以在一个工程中,通常只使用一个对象即可。
      QSqlDatabase db; 
      //加载SQLite数据库驱动
      db = QSqlDatabase::addDatabase("QSQLITE");
      //以.db为后缀,设置数据库文件。 运行时会在当前工作目录下生成mydatabase.db。
      db.setDatabaseName("mydatabase.db");
      //如果想要进一步操作数据库,那就必须进行数据库连接打开操作
      if(db.open())
      {
          qDebug() << "Database open successed!";
      }
      else
      {
          qDebug() << "Database open failed: " << db.lastError() ;
      }
  (5)、访问数据库。
  (6)、关闭数据库。

5、数据库有网络型数据库和单机型数据库。
  (1)、网络型数据库包括: MySQL、Oracle、Microsoft SQL Server等。
  (2)、单机型数据库包括: SQLite、MySQL、Microsoft Access等。
  
  
  
二、Qt SQL模块的主要类和它们的主要函数
1、Qt SQL模块包含的主要类的功能:
  类名称                      功能描述
  QSqlDatabase               用于建立与数据库的连接(重要!!!)
  QSqlDriver                 用于访问具体的SQL数据库的底层抽象类
  QSqlDriverCreator          为某个具体的数据库驱动提供SQL驱动的模板类
  QSqlDriverCreatorBase      所有SQL驱动器的基类
  QSqlDriverPlugin           用于定制QSqlDriver插件的抽象基类
  QSqlError                  SQL数据库错误信息,可以用于访问上一次出错的信息
  QSqlField                  操作数据表或视图的字段的类
  QSqlIndex                  操作数据库的索引的类
  QSqlQuery                  执行各种SQL语句的类(重要!!!)
  QSqlQueryModel             SQL查询结果数据的只读数据模型,用于SELECT查询结果数据记录的只读显示
  QSqlRecord                 封装了数据记录操作的类
  QSqlRelation               用于存储SQL外键信息的类,用于QSqlRelationalTableModel数据源中设置代码字段与关联数据表的关系
  QSqlRelationalTableModel   用于一个数据表的可编辑的数据模型,支持代码字段的外键
  QSqlResult                 访问SQL数据库的抽象接口
  QSqlTableModel             编辑一个单一数据表的数据模型类
  QDataWidgetMapper          用于界面组件与字段之间实现映射,实现字段内容自动显示的类

2、QSqlDatabase类的主要函数接口
  QSqlDatabase用于建立与数据库的连接。 
  对于一个工程而言,该类对象就相当于一个数据库,所以使用一个对象即可。
  一般先加载需要的数据库驱动,然后如果是网络型数据库(如Oracle、MS SQL Server),需设置数据库的登录参数,如主机地址、用户名、登录密码等; 如果是单机型数据库(如SQLite),只需设置数据库文件即可。
(1)、QSqlDatabase addDatabase(const QString & type, const QString & connectionName = QLatin1String(defaultConnection))     
    静态函数,根据数据库驱动名type加载数据库驱动,获取数据库对象。
(2)、void setDatabaseName(const QString & name)
    将连接的数据库名称设置为name,即设置数据库文件(数据库文件后缀为.db)。 要生效,必须在打开数据库之前设置名称。 (用于单机型数据库)
(3)、void setHostName(const QString & host)
    将连接的主机名设置为host。 要生效,必须在打开数据库之前设置,无默认值。 (用于网络型数据库)
(4)、void setPassword(const QString & password)
    将连接的密码设置为password。 要生效,必须在打开数据库之前设置,无默认值。 (用于网络型数据库)
(5)、void setUserName(const QString & name)
    将连接的用户名设置为name。 要生效,必须在打开数据库之前设置,无默认值。 (用于网络型数据库)
(6)、bool open() 
    使用当前连接值打开数据库连接。 成功返回true,失败返回false。 可以使用lastError()函数检索错误信息。
    bool open(const QString & user, const QString & password)
    用指定的用户名和密码打开数据库连接。 成功返回true,失败返回false。 可以使用lastError()函数检索错误信息。

3、QSqlQuery类的主要函数接口
  QSqlQuery可以执行各种SQL语句。
  在打开成功的数据库中,通过QSqlQuery的函数接口对数据库内容进行访问。
  访问数据库的操作主要包括: 创建表,向数据库表中插入数据、删除数据、更新数据、查询数据。
  注意,表只创建一次,其它增删改查操作可以做无数次。
(1)、QSqlQuery(const QString & query = QString(), const QSqlDatabase & db = QSqlDatabase())
    得到访问数据库的QSqlQuery对象。
    如果query不是空字符串,则会执行query语句。
    如果未指定db,则使用默认数据库,系统会自动完成跟数据库的关联。
(2)、bool exec(const QString & query)
    执行SQL语句访问数据库。 
    如果执行成功则返回true并将查询状态设为active,否则返回false。
    注意,执行查询后,查询将定位在无效记录上,必须导航到有效记录才能检索数据值(如使用next())。
(3)、int at() const
    得到当前记录查询位置,第一条记录的为0
(4)、bool first()
    检索结果中的第一条记录
(5)、bool last()
    检索结果中的最后一条记录
(6)、bool next()
    检索结果中的下一条记录。
    如果无法检索记录,则结果将位于最后一条记录之后,并返回false。 如果成功检索到记录,则返回true。
(7)、QVariant value(const QString & name) const
    返回当前记录中名为name的字段的值。
(8)、bool prepare(const QString & query)
    提前准备好SQL语句以供执行。
    查询语句可能包含绑定值的占位符,如":名称"或者"?",但在同一查询中二者不可混用。
(9)、void addBindValue(const QVariant & val, QSql::ParamType paramType = QSql::In);
    使用位置值绑定,将值val添加到值列表中。
    addBindValue()调用顺序决定值val绑定到哪个占位符。
(10)、void bindValue(const QString & placeholder, const QVariant & val, QSql::ParamType paramType = QSql::In)
    在准备好的SQL语句中将占位符placeholder设置为值val。

4、数据获取和界面显示
(1)、Qt采用Model/View结构进行数据库内容的界面显示和编辑。
(2)、QTableView是常用的数据库内容显示视图组件。
(3)、QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel是常用的数据库操作的数据模型类。
(4)、数据库相关数据模型类的继承关系:
    QAbstractTableModel
             |
       QSqlQueryModel
             |
       QSqlTableModel
             |
    QSqlRelationalTableModel
(5)、QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel三者区别:
    a、QSqlQueryModel通过设置SQL语句查询获取数据库的内容,但是数据是只读的,不能进行编辑。
    b、QSqlTableModel直接设置一个数据表的名称,可以获取数据表的全部记录,且结果是可编辑的,只要设置为QTableView的模型后就可显示和编辑数据。
    c、QSqlRelationalTableModel编辑一个数据表,并且可以将代码字段通过关系与代码表关联,将代码字段的编辑转换为直观的内容选择编辑,即支持外键。
(6)、根据官方手册提示,通过重写QSqlQueryModel的setData()和flags()函数,可实现数据的编辑,见"七代码示例"。
    a、bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
    b、Qt::ItemFlags flags(const QModelIndex & index) const;

    
    
三、SQLite数据库简介
0、本文及后续文章,采用SQLite数据库作为实例,来研究Qt SQL数据库编程功能。
1、SQLite是一种无需服务器、无需进行任何配置的数据库。
2、所有的数据表、索引等数据库元素全都存储在一个文件里,在应用程序里使用SQLite数据库可以当作一个文件来使用。
3、SQLite是可以跨平台使用的数据库,在不同平台之间可以随意复制数据库。
4、SQLite的驱动库文件很小,包含完整功能的驱动可以小到只有500KB。
5、SQLite是一种开源免费使用的数据库。
6、SQLite Expert是SQLite数据库可视化管理工具,可以从官网下载,自带SQLite数据库驱动。

四、SQL语法:
1、创建表:
(1)、举例:
    /*
     * 员工表: staff
     * 字段名: id name age address salary
    */
(2)、代码:
    //创建表只运行一次,之后注释掉
    QString sqlCreateTable("create table staff(id integer primary key autoincrement, "
                           "name varchar(20), "
                           "age int, "
                           "address varchar(50), "
                           "salary int); ");
    if(!query.exec(sqlCreateTable))
    {
        qDebug() << "create table error" << m_db.lastError();
    }
(3)、说明:
    因为id是自动增长的,所以插入数据时,可以不用插入id。
    QString sqlInsert("insert into staff(name, age, address, salary) values('张三', 20, '广州市天河区', 12000);");
    if(!query.exec(sqlInsert))
    {
        qDebug() << "insert into error" << m_db.lastError();
    }

2、插入操作:
(1)、语法:
    INSERT INTO TABLE_NAME(column1, column2, column3, ... , columnN) VALUES(value1, value2, value3, ... , valueN);
    插入记录
(2)、说明:
    INSERT INTO 是关键字
    TABLE_NAME 是表名
    VALUES 是关键字
    
3、删除操作:
(1)、语法:
    DELETE FROM TABLE_NAME WHERE [condition];
    删除记录
(2)、说明:
    DELETE FROM 是关键字
    TABLE_NAME 是表名
    WHERE 是条件的关键字
    [condition] 是条件表达式
(3)、举例:
    QString sqlDelete = QString("delete from staff where id = %1;").arg(id);
(4)、注意:
    经测试,某字段若定义为自动增长,那删除某条记录后,该字段的值就会被永久删除。(如id定义为自动增长,删除id=3的记录,则以后再添加记录,id = 3不会再出现)
  
4、更新操作:
(1)、语法:
    UPDATE TABLE_NAME SET column1 = value1, column2 = value2, ... , columnN = valueN WHERE [condition]
    更新某记录的某字段值
(2)、说明:
    UPDATE 是关键字
    TABLE_NAME 是表名
    SET 是关键字
    column1 = value1 是要修改的字段名和所对应的值
    WHERE 是条件的关键字
    [condition] 是条件表达式
 
5、查询操作:
(1)、语法:
    SELECT column1, column2, ... , columnN FROM TABLE_NAME;
    从表中查询出指定字段对应的值
(2)、说明:
    SELECT 是关键字
    column1, column2, ... , columnN 是列的字段名
    FROM 是关键字
    TABLE_NAME 是表名
(3)、语法:
    SELECT * FROM TABLE_NAME;
    从表中查询出所有字段对应的值    
    
    
    
五、代码示例QSqlQuery + Widget:
//itemfrom.h

#ifndef ITEMFROM_H
#define ITEMFROM_H

#include

namespace Ui { class itemFrom;}

class itemFrom : public QMainWindow
{
    Q_OBJECT

public:
    explicit itemFrom(QWidget * parent = nullptr);
    ~itemFrom();

    void setStaffInfo(int id, QString name, int age, QString addr, int salary);

private:
    Ui::itemFrom * ui = nullptr;
};

#endif // ITEMFROM_H

//itemfrom.cpp

#include "itemfrom.h"
#include "ui_itemfrom.h"

itemFrom::itemFrom(QWidget * parent) : QMainWindow(parent)
{
    ui = new Ui::itemFrom();
    ui->setupUi(this);
}

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

void itemFrom::setStaffInfo(int id, QString name, int age, QString addr, int salary)
{
    ui->idLabel->setText(QString::number(id));
    ui->nameLabel->setText(name);
    ui->ageLabel->setText(QString::number(age));
    ui->addrLabel->setText(addr);
    ui->salaryLabel->setText(QString::number(salary));
}

//mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include
#include
#include
#include

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget * parent = nullptr);
    ~MainWindow();

private slots:
    void on_addBtn_clicked();
    void on_updateBtn_clicked();
    void on_deleteBtn_clicked();
    void on_selectBtn_clicked();

private:
    Ui::MainWindow * ui = nullptr;

    QSqlDatabase m_db;
};

#endif // MAINWINDOW_H

//mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "itemfrom.h"
#include

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

    m_db = QSqlDatabase::addDatabase("QSQLITE");
    m_db.setDatabaseName("company.db");
    if(!m_db.open())
    {
        qDebug() << "open database error" << m_db.lastError();
    }

    //创建表只运行一次,下次运行要注释掉!!!
    //QSqlQuery构造不传参,会使用默认数据库sqlite
    //员工表: staff
    //字段名: id name age address salary
    // QSqlQuery query;
    // QString sqlCreateTable("create table staff(id integer primary key autoincrement, "
    //                        "name varchar(20),"
    //                        "age int,"
    //                        "address varchar(50),"
    //                        "salary int);");
    // if(!query.exec(sqlCreateTable))
    // {
    //     qDebug() << "create table error" << m_db.lastError();
    // }
}

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

void MainWindow::on_addBtn_clicked()
{
    QString name = ui->nameLineEdit->text();
    int age = ui->ageLineEdit->text().toInt();
    QString addr = ui->addrLineEdit->text();
    int salary = ui->salaryLineEdit->text().toInt();

    //ID定义时是自动增长,不用从UI获取,不用插入到数据库
    QSqlQuery query;
    QString sqlInsert = QString("insert into staff(name, age, address, salary) values('%1', %2, '%3', %4);").arg(name).arg(age).arg(addr).arg(salary);
    if(!query.exec(sqlInsert))
    {
        qDebug() << "insert into error" << m_db.lastError();
    }

    on_selectBtn_clicked();
}

void MainWindow::on_updateBtn_clicked()
{
    //只更新地址
    int id = ui->idLineEdit->text().toInt();
    QString addr = ui->addrLineEdit->text();

    QSqlQuery query;
    QString sqlUpdate = QString("update staff set address = '%1' where id = %2;").arg(addr).arg(id);
    if(!query.exec(sqlUpdate))
    {
        qDebug() << "update error" << m_db.lastError();
    }

    on_selectBtn_clicked();
}

void MainWindow::on_deleteBtn_clicked()
{
    int id = ui->idLineEdit->text().toInt();

    QSqlQuery query;
    QString sqlDelete = QString("delete from staff where id = %1;").arg(id);
    if(!query.exec(sqlDelete))
    {
        qDebug() << "delete error" << m_db.lastError();
    }

    on_selectBtn_clicked();
}

void MainWindow::on_selectBtn_clicked()
{
    ui->listWidget->clear();

    QSqlQuery query;
    QString sqlSelect("select * from staff;");
    if(!query.exec(sqlSelect))
    {
        qDebug() << "select error" << m_db.lastError();
    }

    while(query.next())
    {
        int id = query.value("id").toInt();
        QString name = query.value("name").toString();
        int age = query.value("age").toInt();
        QString addr = query.value("address").toString();
        int salary = query.value("salary").toInt();

        itemFrom * staffItem = new itemFrom(ui->listWidget);
        staffItem->setStaffInfo(id, name, age, addr, salary);
        QListWidgetItem * item = new QListWidgetItem(ui->listWidget);
        item->setSizeHint(QSize(531, 34));
        ui->listWidget->addItem(item);
        ui->listWidget->setItemWidget(item, staffItem);
    }
}

//main.cpp

#include "mainwindow.h"
#include

int main(int argc, char * argv[])
{
    QApplication a(argc, argv);

    MainWindow w;
    w.show();

    QStringList drivers = QSqlDatabase::drivers();
    foreach (QString driver, drivers)
    {
        qDebug() << driver;
    }

    return a.exec();
}

六、代码示例QSqlQueryModel + QTableView:
//mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include
#include
#include
#include
#include
#include

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget * parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow * ui = nullptr;
    QSqlDatabase m_db;
};

#endif // MAINWINDOW_H

//mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

    m_db = QSqlDatabase::addDatabase("QSQLITE");
    m_db.setDatabaseName("company.db");
    if(!m_db.open())
    {
        qDebug() << "open database error" << m_db.lastError();
    }

    //只创建表一次,然后注释掉
    // QSqlQuery query;
    // QString sqlCreateTable = QString("create table staff(id integer primary key autoincrement,"
    //                                  "name varchar(20),"
    //                                  "age integer,"
    //                                  "address varchar(50),"
    //                                  "salary integer);");
    // if(!query.exec(sqlCreateTable))
    // {
    //     qDebug() << "create table error" << m_db.lastError();
    // }

    //插入数据后也需要注释掉
    // QString sqlInsert = QString("insert into staff(name, age, address, salary) values('zx', 8, '工业园区', 55000);");
    // if(!query.exec(sqlInsert))
    // {
    //     qDebug() << "insert error" << m_db.lastError();
    // }

    //创建QSqlQueryModel对象
    QSqlQueryModel * model = new QSqlQueryModel;
    //执行SQL语句, 将查询出来的结果转换为model对象
    model->setQuery("select name, age, address, salary from staff;");
    //根据需求设置表头信息
    model->setHeaderData(0, Qt::Horizontal, "Name");
    model->setHeaderData(1, Qt::Horizontal, "Age");
    model->setHeaderData(2, Qt::Horizontal, "Address");
    model->setHeaderData(3, Qt::Horizontal, "Salary");

    //给UI控件设置一个模型
    QTableView * view = new QTableView(ui->centralwidget);
    view->setFixedSize(QSize(this->width(), this->height()));
    view->setModel(model);
    view->show();
}

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

七、代码示例自定义可编辑QSqlQueryModel + QTableView:

//editquerymodel.h

#ifndef EDITQUERYMODEL_H
#define EDITQUERYMODEL_H

#include

class EditQueryModel : public QSqlQueryModel
{
public:
    explicit EditQueryModel(QObject * parent = nullptr);

    bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) override;
    Qt::ItemFlags flags(const QModelIndex & index) const override;

private:
    //更新数据,相当于将数据库的数据查询出来,转换成model
    void refresh();
    //根据需求来定义修改表中内容的接口
    bool setName(int useId, const QString & name);
};

#endif // EDITQUERYMODEL_H

//editquerymodel.cpp

#include "editquerymodel.h"
#include

EditQueryModel::EditQueryModel(QObject * parent) : QSqlQueryModel{parent}
{
}

bool EditQueryModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    //判断数据的合法性: 是否为有效的列
    if(index.column() < 1 || index.column() > 4)
    {
        return false;
    }

    //获取列所对应的id
    QModelIndex primaryIndex = QSqlQueryModel::index(index.row(), 0);
    int id = this->data(primaryIndex).toInt();

    //在修改前将model数据清除
    this->clear();

    bool bOk = false;
    //根据需求,来修改对应列
    if(index.column() == 1)
    {
        bOk = setName(id, value.toString());
    }

    //刷新数据
    refresh();

    return bOk;
}

Qt::ItemFlags EditQueryModel::flags(const QModelIndex & index) const
{
    //获取单元格的编辑状态
    Qt::ItemFlags flag = QSqlQueryModel::flags(index);

    //给name列增加一个可编辑的标志
    if(index.column() == 1)
    {
        flag = flag | Qt::ItemIsEditable;
    }

    return flag;
}

void EditQueryModel::refresh()
{
    this->setQuery("select * from staff;");

    //如果不重新设置名字,会默认都是数据库表的表头
    this->setHeaderData(0, Qt::Horizontal, "ID");
    this->setHeaderData(1, Qt::Horizontal, "Name");
    this->setHeaderData(2, Qt::Horizontal, "Age");
    this->setHeaderData(3, Qt::Horizontal, "Address");
    this->setHeaderData(4, Qt::Horizontal, "Salary");
}

bool EditQueryModel::setName(int useId, const QString & name)
{
    QSqlQuery query;

    //"?"是占位符
    query.prepare("update staff set name = ? where id = ?;");
    //调用顺序决定绑定哪个占位符
    query.addBindValue(name);
    query.addBindValue(useId);

    return query.exec();
}

//mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include
#include
#include
#include
#include
#include

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget * parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow * ui = nullptr;
    QSqlDatabase m_db;
};
#endif // MAINWINDOW_H

//mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "editquerymodel.h"

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

    m_db = QSqlDatabase::addDatabase("QSQLITE");
    m_db.setDatabaseName("company.db");
    if(!m_db.open())
    {
        qDebug() << "open database error" << m_db.lastError();
    }

    //QSqlQuery query;
    // QString sqlCreateTable = QString("create table staff(id integer primary key autoincrement,"
    //                                  "name varchar(20),"
    //                                  "age integer,"
    //                                  "address varchar(50),"
    //                                  "salary integer);");
    // if(!query.exec(sqlCreateTable))
    // {
    //     qDebug() << "create table error" << m_db.lastError();
    // }

    // QString sqlInsert = QString("insert into staff(name, age, address, salary) values('李四', 25, '广州', 15000);");
    // if(!query.exec(sqlInsert))
    // {
    //     qDebug() << "insert error" << m_db.lastError();
    // }

    //创建模型对象
    EditQueryModel * model = new EditQueryModel();
    model->setQuery("select id, name, age, address, salary from staff;");
    model->setHeaderData(0, Qt::Horizontal, "ID");
    model->setHeaderData(1, Qt::Horizontal, "Name");
    model->setHeaderData(2, Qt::Horizontal, "Age");
    model->setHeaderData(3, Qt::Horizontal, "Address");
    model->setHeaderData(4, Qt::Horizontal, "Salary");

    //创建表格控件
    QTableView * view = new QTableView(ui->centralwidget);
    view->setModel(model);
    view->setFixedSize(QSize(this->width(), this->height()));
    view->show();
}

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


  


 

你可能感兴趣的:(Qt,qt,数据库,开发语言)