Qt数据库操作-QSqlQueryModel 的使用

QSqlQueryModel 功能概述

QSqlQueryModel 是 QSqlTableModel 的父类。QSqlQueryModel 封装了执行 SELECT 语句从数据库查询数据的功能,但是 QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据。QSqlQueryModel 类的主要函数如下:

接口函数 功能描述
void clear() 清除数据模型,释放所有获得的数据
QSqlError lastError() 返回上次的错误,可以获取错误的类型和文本信息
QSqlQuery query() 返回当前关联的 QSqlQuery 对象
void setQuery(QSqlQuery& query) 设置一个 QSqlQuery 对象,获取数据
void setQuery(QString& query) 设置一个 SELECT 语句创建查询,获取数据
QSqlRecord record() 返回一个空记录,包含当前查询的字段信息
QSqlRecord record(int row) 返回行号为 row 的记录
int rowCount() 返回查询到的记录条数
int columnCount() 返回查询的字段个数
void setHeaderData(int section, Qt::Orientation orientation, QVariant& value) 设置表头数据,一般用于设置字段的表头标题

使用 QSqlQueryModel 作为数据模型从数据库查询数据,只需要使用 setQuery() 函数设置一个 SELECT 查询语句即可。QSqlQueryModel 可以作为 QTableView 等视图组件的数据源,也可以使用 QDataWidgetMapper 创建字段与界面组件的映射,只是查询出来的数据是不可编辑的。

使用 QSqlQueryModel 实现数据查询

实例功能

使用 QSqlQueryModel 可以从一个数据表或多个数据表里查询数据,只要设计好 SELECT 语句即可。由于 QSqlQueryModel 读出的数据是只读的,所以没有编辑保存等功能,主窗口定义如下:

cpp 复制代码
class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QLabel  *LabInfo;

    QSqlDatabase  DB; //数据库

    QSqlQueryModel  *qryModel; //数据模型

    QItemSelectionModel *theSelection; //选择模型

    QDataWidgetMapper   *dataMapper;//数据界面映射

    void    openTable();//打开数据表
    void    refreshTableView();//移动记录时刷新TableView的当前行
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:

// QTableView的SelectionModel的行发生了变化,进行处理
    void on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous);
///
    void on_actOpenDB_triggered();

    void on_actRecFirst_triggered();

    void on_actRecPrevious_triggered();

    void on_actRecNext_triggered();

    void on_actRecLast_triggered();

private:
    Ui::MainWindow *ui;
};

这里定义了 QSqlQueryModel 类型的数据模型变量 qryModel,也定义了数据库、选择模型和数据界面映射的变量。refreshTableView() 函数用于记录移动后刷新 TableView 上的当前行位置。自定义槽函数 on_currentRowChanged() 在选择模型的当前变化时,处理 Photo 字段的查询与照片显示。

打开数据库

openTable() 用于查询数据,简历界面显示等具体操作,代码如下:

cpp 复制代码
void MainWindow::openTable()
{//打开数据表
    qryModel=new QSqlQueryModel(this);
    qryModel->setQuery("SELECT empNo, Name, Gender, Height, Birthday, Mobile, Province, City, Department, "
                       " Education, Salary FROM employee ORDER BY empNo");
    if (qryModel->lastError().isValid())
    {
        QMessageBox::critical(this, "错误", "数据表查询错误,错误信息\n"+qryModel->lastError().text(),
                                 QMessageBox::Ok,QMessageBox::NoButton);
        return;
    }

   LabInfo->setText(QString::asprintf("记录条数:%d",qryModel->rowCount()));

    qryModel->setHeaderData(0,Qt::Horizontal,"工号");
    qryModel->setHeaderData(1,Qt::Horizontal,"姓名");
    qryModel->setHeaderData(2,Qt::Horizontal,"性别");
    qryModel->setHeaderData(3,Qt::Horizontal,"身高");
    qryModel->setHeaderData(4,Qt::Horizontal,"出生日期");
    qryModel->setHeaderData(5,Qt::Horizontal,"手机");
    qryModel->setHeaderData(6,Qt::Horizontal,"省份");
    qryModel->setHeaderData(7,Qt::Horizontal,"城市");
    qryModel->setHeaderData(8,Qt::Horizontal,"部门");
    qryModel->setHeaderData(9,Qt::Horizontal,"学历");
    qryModel->setHeaderData(10,Qt::Horizontal,"工资");

    theSelection=new QItemSelectionModel(qryModel);
    //选择行变化时
    connect(theSelection,SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
                this,SLOT(on_currentRowChanged(QModelIndex,QModelIndex)));

    ui->tableView->setModel(qryModel);
    ui->tableView->setSelectionModel(theSelection);
//    ui->tableView->resizeColumnsToContents();
//    ui->tableView->horizontalHeader()->setStretchLastSection(true);

//创建数据映射
    dataMapper= new QDataWidgetMapper();
    dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
    dataMapper->setModel(qryModel);
    dataMapper->addMapping(ui->dbSpinEmpNo,0);//"empNo";
    dataMapper->addMapping(ui->dbEditName,1);//"Name";
    dataMapper->addMapping(ui->dbComboSex,2);//"Gender";

    dataMapper->addMapping(ui->dbSpinHeight,3);//"Height";
    dataMapper->addMapping(ui->dbEditBirth,4);//"Birthday";
    dataMapper->addMapping(ui->dbEditMobile,5);//"Mobile";

    dataMapper->addMapping(ui->dbComboProvince,6);//"Province";
    dataMapper->addMapping(ui->dbEditCity,7);//"City";
    dataMapper->addMapping(ui->dbComboDep,8);//"Department";

    dataMapper->addMapping(ui->dbComboEdu,9);//"Education";
    dataMapper->addMapping(ui->dbSpinSalary,10);//"Salary";

    dataMapper->toFirst();

    ui->actOpenDB->setEnabled(false);
}

程序首先创建了 QSqlQueryModel 类型的私有变量 qryModel,然后调用 setQuery() 函数设置了 SELECT 查询语句,SELECT 语句从 employee 表里查询除了 Memo 和 Photo 之外的所有其他字段。使用 setHeadData() 函数为每个字段设置显示标题,为了代码简化,这里直接使用字段的序号。

qryModel 创建了选择模型 theSelection,并将其 currentRowChanged() 信号和自定义槽函数关联,查询出数据显示在界面上,槽函数代码如下:

cpp 复制代码
void MainWindow::on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{
    Q_UNUSED(previous);
    if (!current.isValid())
    {
        ui->dbLabPhoto->clear();
        return;
    }

    dataMapper->setCurrentModelIndex(current);

    bool first=(current.row()==0); //是否首记录
    bool last=(current.row()==qryModel->rowCount()-1);//是否尾记录

    ui->actRecFirst->setEnabled(!first); //更新使能状态
    ui->actRecPrevious->setEnabled(!first);
    ui->actRecNext->setEnabled(!last);
    ui->actRecLast->setEnabled(!last);

    int curRecNo=theSelection->currentIndex().row();
    QSqlRecord  curRec=qryModel->record(curRecNo); //获取当前记录
    int empNo=curRec.value("EmpNo").toInt();

    QSqlQuery query; //查询当前empNo的Memo和Photo字段的数据
    query.prepare("select EmpNo, Memo, Photo from employee where EmpNo = :ID");
    query.bindValue(":ID",empNo);
    query.exec();
    query.first();

    QVariant    va=query.value("Photo");//
    if (!va.isValid())  //图片字段内容为空
       ui->dbLabPhoto->clear();
    else
    {//显示照片
        QByteArray data=va.toByteArray();
        QPixmap pic;
        pic.loadFromData(data);
        ui->dbLabPhoto->setPixmap(pic.scaledToWidth(ui->dbLabPhoto->size().width()));
    }

    QVariant    va2=query.value("Memo");//显示备注
    ui->dbEditMemo->setPlainText(va2.toString());
}

记录移动

用于数据映射的 QDataWidgetMapper 类设置数据模型后,总是指向数据模型的当前记录。QDataWidgetMapper 有四个函数进行当前记录移动,分别是 toFirst()toLast()toNext()toPrevious()。当前记录移动时,会引起数据模型关联的选择模型发射 currentRowChanged() 信号,触发槽函数。工具栏的四个移动按钮代码如下:

cpp 复制代码
void MainWindow::on_actRecFirst_triggered()
{ //首记录
    dataMapper->toFirst();
    refreshTableView();
}

void MainWindow::on_actRecPrevious_triggered()
{ //前一条记录
    dataMapper->toPrevious();
    refreshTableView();
}

void MainWindow::on_actRecNext_triggered()
{//后一条记录
    dataMapper->toNext();
    refreshTableView();
}

void MainWindow::on_actRecLast_triggered()
{//最后一条记录
    dataMapper->toLast();
    refreshTableView();
}

参考资料:https://github.com/0voice

相关推荐
极客先躯1 分钟前
Redis 安装与配置指南
数据库·redis·数据验证·安装说明·编译和安装·redis 集群配置·查看集群
YaenLi39 分钟前
MySQL 安装部署
linux·数据库·mysql
乄北城以北乀1 小时前
一.MySQL程序简介
数据库·mysql
炭烤毛蛋1 小时前
Ubuntu 磁盘修复
linux·数据库·ubuntu
代码代码快快显灵1 小时前
Redis之秒杀活动
数据库·redis·缓存·秒杀活动
一水鉴天3 小时前
为AI聊天工具添加一个知识系统 之27 支持边缘计算设备的资源存储库及管理器
数据库·人工智能·前端框架
拾忆,想起4 小时前
Spring拦截链揭秘:如何在复杂应用中保持控制力
java·数据库·spring
Bytebase5 小时前
AWS re:Invent 2024 现场实录 - It‘s all about Scale
运维·数据库·dba·开发者·数据库管理·devops
GreatSQL5 小时前
【GreatSQL优化器-10】find_best_ref
数据库
feiyangqingyun5 小时前
Qt监控系统远程网络登录/请求设备列表/服务器查看实时流/回放视频/验证码请求
服务器·网络·qt