11-2_Qt 5.9 C++开发指南_QSqlQueryModel的使用(QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据)

这篇具有很好参考价值的文章主要介绍了11-2_Qt 5.9 C++开发指南_QSqlQueryModel的使用(QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 QSqlQueryModel 功能概述

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

11-2_Qt 5.9 C++开发指南_QSqlQueryModel的使用(QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据),# Qt 5.9 C++开发指南,qt,c++,sqlite

QSqlQueryModel 类的主要接口函数见表 11-10(省略了函数中的 const 关键字和缺省参数)。

11-2_Qt 5.9 C++开发指南_QSqlQueryModel的使用(QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据),# Qt 5.9 C++开发指南,qt,c++,sqlite

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

2 使用 QSqlQueryModel 实现数据查询

2.1 实例功能

使用 QSqlQueryModel 可以从一个数据表或多个数据表里查询数据,只需设计好 SELECT 语句即可。实例 samp11_2 使用 QSqQueryModel从employee 表里查询记录,并在界面上显示,运行窗口见下图。

11-2_Qt 5.9 C++开发指南_QSqlQueryModel的使用(QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据),# Qt 5.9 C++开发指南,qt,c++,sqlite

窗口工具栏上几个工具栏按钮只有打开数据库和记录移动功能,记录移动通过调用QdataWidget-Mapper 类的记录移动功能实现。窗口上没有数据编辑和保存功能,因为 QSqlQueryModel 查询出来的数据是只读的。

2.2 可视化UI设计

samp11_2采用可视化UI设计,具体框架如下图所示

11-2_Qt 5.9 C++开发指南_QSqlQueryModel的使用(QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据),# Qt 5.9 C++开发指南,qt,c++,sqlite

2.3 主窗口类定义(去除自动生成的槽函数)

#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:
    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);

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

这里定义了 QSqlQueryModel 类型的数据模型变量 qryModel,也定义了数据库、选择模型和数据界面映射的变量。refreshTableView()函数用于记录移动后刷新 tableView 上的当前行位置。

自定义槽函数on_currentRowChanged()在选择模型的当前行变化时,处理 Photo 字段的查询与照片显示。

2.4 打开数据库

工具栏上的“打开数据库”按钮对应 actOpenDB,选择SQLite数据库文件,然后调用openTable()函数打开数据库。槽函数 on_actOpenDB_triggered()的代码与实例 samp11_1 完全一样,这里不再列出。

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

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 之外的所有其他字段。

使用 setHeaderData()函数为每个字段设置显示标题,为使代码简化,这里直接使用了字段的序号。

下面是槽函数on_currentRowChange()的代码:

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());
}

这个函数实现了3个功能,第1个功能是更新数据映射的行号,即:

dataMapper->setCurrentModelIndex(current); //更新数据映射的行号

使窗口上的字段关联的显示组件刷新显示当前记录的内容

第 2个功能是根据当前行号,判断是否是首记录或尾记录,以此更新界面上 4 个记录移动的Action的使能状态。
第3 个功能是获取当前记录的 EmpNo 字段的值 (即员工编号),然后用一个 QSqlQuery 变量query 执行查询语句,只查询出这个员工的 Memo 和 Photo 字段的数据,然后在界面元件上显示。这里使用了 QSqlQuery 类,它用来执行任意的 SQL 语句。

在QSqlQueryModel 类的变量 qryModel 里设置 SELECT 语句时,并没有查询所有字段,因为 Photo是BLOB 字段,全部查询出来后必然占用较大内存,而且在做记录遍历时,如果存在 BLOB 字段数据执行速度会很慢。所以,这个实例里将普通字段的查询用 QSqlQueryModel 来查询并显示,而 Memo和 Photo 字段数据的查询采用按需查询的方式,这样可以减少内存消耗,提高记录遍历时的执行速度

openTable()函数剩余的部分是设置 tableView 的数据模型和选择模型,然后创建数据界面映射变量 dataMapper,设置各个界面组件与字段的映射关系。

2.5 记录移动

用于数据映射的 QDataWidgetMapper 类设置数据模型后,总是指向数据模型的当前记录。QDataWidgetMapper 有 4 个函数进行当前记录的移动,分别是 toFirst()、toLast()、toNext()和toPrevious()。当前记录移动时,会引起数据模型关联的选择模型发射 currentRowChanged()信号,也就会执行关联的自定义槽函数 on currentRowChanged()。
工具栏上有 4 个记录移动的按钮,它们调用 QDataWidgetMapper 的记录移动函数实现记录移动,4个Action 的槽函数代码如下:

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();
}

使用QDataWidgetMapper 的记录移动操作后,QDataWidgetMapper 会移动到新的记录上,映射了字段的界面组件也会自动显示新记录的字段的数据。但是,tableView 的当前行并不会自动变化,所以需要调用 refreshTableView()函数刷新 tableView 的显示,refreshTableView()函数的代码如下:文章来源地址https://www.toymoban.com/news/detail-613402.html

void MainWindow::refreshTableView()
{//刷新tableView的当前选择行
    int index=dataMapper->currentIndex();
    QModelIndex curIndex=qryModel->index(index,1);//
    theSelection->clearSelection();//清空选择项
    theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//设置刚插入的行为当前选择行
}

到了这里,关于11-2_Qt 5.9 C++开发指南_QSqlQueryModel的使用(QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 09-1_Qt 5.9 C++开发指南_Qchart概述

    Qt Charts 可以很方便地绘制常见的折线图、柱状图、饼图等图表,不用自己耗费时间和精力开发绘图组件或使用第三方组件了。 本章首先介绍 Qt Charts 的基本特点和功能,以画折线图为例详细说明 Qt Charts 各主要部件的操作方法,再介绍各种常用图表的绘图方法,最后介绍鼠标

    2024年02月13日
    浏览(41)
  • 16-1_Qt 5.9 C++开发指南_多语言界面

    有些软件需要开发多语言界面版本,如中文版和英文版,并且在软件里可以方便地切换界面语言。Qt 为多语言界面提供了很好的支持,使用 Qt 的一些规则和工具,可以很方便地为应用程序开发提供多语言界面支持。 用 Qt 开发多语言界面应用程序,主要包括以下几个步骤。

    2024年02月14日
    浏览(33)
  • 07-1_Qt 5.9 C++开发指南_文件系统及文件读写_文本文件读写(使用 QTextStream 进行文件读写更为方便)

    文本文件是指以纯文本格式存储的文件,例如用 Qt Creator 编写的 C++程序的头文件 (.h 文件)和源程序文件 (.cpp 文件)。HTML 和 XML 文件也是纯文本文件,只是其读取之后需要对内容进行解析之后再显示。 Qt 提供了两种读写纯文本文件的基本方法, 一种是用 QFile 类的 IODevice 读写

    2024年02月13日
    浏览(42)
  • 16-3_Qt 5.9 C++开发指南_使用QStyle 设置界面外观_实现不同系统下的界面效果的匹配

    Qt 是一个跨平台的类库,相同的界面组件在不同的操作系统上显示效果是不一样的。QStyle是封装了 GUI 界面组件外观的抽象类,Qt 定义了 QStyle 类的一些子类,应用于不同的操作系统如QWindowsStyle和QMacStyle 等。这些样式是 QtGUI 模块自带的,在不同的平台上编译运行的程序具有缺

    2024年02月13日
    浏览(40)
  • 16-4_Qt 5.9 C++开发指南_Qt 应用程序的发布

    用 Qt 开发一个应用程序后,将应用程序提供给用户在其他计算机上使用就是应用程序的发布。应用程序发布一般会提供一个安装程序,将应用程序的可执行文件及需要的运行库安装到用户计算机上,即使用户计算机上没有安装 Qt 也能正常运行安装的程序。 Qt的应用程序发布

    2024年02月14日
    浏览(40)
  • 15-1_Qt 5.9 C++开发指南_Qt多媒体模块概述

    多媒体功能指的主要是计算机的音频和视频的输入、输出、显示和播放等功能,Qt 的多媒体模块为音频和视频播放、录音、摄像头拍照和录像等提供支持,甚至还提供数字收音机的支持。本章将介绍 Qt 多媒体模块的功能和使用。 Qt 多媒体模块提供了很多类,可以实现如下的

    2024年02月13日
    浏览(38)
  • 04-6_Qt 5.9 C++开发指南_QListWidget和QToolButton

    Qt 中用于项 (Item)处理的组件有两类, 一类是 Item Views ,包括 QListView、QTreeView、QTableView、QColumnView 等; 另一类是 Item Widgets ,包括 QListWidget、QTreeWidget 和QTableWidget。 Item Views 基于模型/视图(Model/Vicw)结构,视图 (View)与模型数据(Model Data)关联实现数据的显示和编辑,模型/视图结

    2024年02月13日
    浏览(37)
  • 04-5_Qt 5.9 C++开发指南_QComboBox和QPlainTextEdit

    QComboBox 是下拉列表框组件类,它提供一个下拉列表供用户选择,也可以直接当作一个QLineEdit 用作输入。OComboBox 除了显示可见下拉列表外,每个项 (item,或称列表项)还可以关联一个 QVariant 类型的变量,用于存储一些不可见数据。 QPlainTextEdit 是一个多行文本编辑器,用于显示

    2024年02月14日
    浏览(42)
  • 08-3_Qt 5.9 C++开发指南_Graphics View绘图架构

    采用QPainter 绘图时需要在绘图设备的 paintEvent()事件里编写绘图的程序,实现整个绘图过程。这种方法如同使用 Windows 的画图软件在绘图,绘制的图形是位图,这种方法适合于绘制复杂性不高的固定图形,不能实现图件的选择、编辑、拖放、修改等功能。 Qt 为绘制复杂的可交

    2024年02月13日
    浏览(31)
  • 04-4_Qt 5.9 C++开发指南_时间日期与定时器

    时间日期是经常遇到的数据类型,Qt 中时间日期类型的类如下。 QTime:时间数据类型,仅表示时间,如 15:23:13。 QDate:日期数据类型,仅表示日期,如2017-4-5. QDateTime:日期时间数据类型,表示日期和时间,如2017-03-23 08:12:43. Qt 中有专门用于日期、时间编辑和显示的 界面组件 ,介

    2024年02月14日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包