当前位置: 首页 > news >正文

QT数据库(二):QSqlQueryModel实现数据查询

QSqlQueryModel 可以设置任意的 SELECT 语句来从数据库中查询数据,可以查询一个数据表部分字段的数据,也可以是多个数据表组合的数据。该模型的数据是只读的,即使在界面上修改了QSqlQueryModel 模型的数据,也不能将所做的修改提交到数据库。

要从数据库查询数据并将其作为 QSqlQueryModel 的数据源,需要运行函数 setQuery()

有两种原型:

void QSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase())

参数 query 是一条完整的 SELECT 查询语句;参数 db 是数据库连接,若不指定数据库连接, 就用程序默认的数据库连接。

void QSqlQueryModel::setQuery(QSqlQuery &&query)

QSqlQuery 是可以运行任何 SQL 语句的类,当然也能运行 SELECT 语句从数据库获取数据。

查询出数据后,可以用 QSqlQueryModel 的函数 record()访问数据记录。

//1. 创建数据模型,查询数据qryModel=new QSqlQueryModel(this);qryModel->setQuery("SELECT empNo, Name, Gender,  Birthday,  Province,  Department, "" Salary FROM employee ORDER BY empNo",DB);if (qryModel->lastError().isValid()){QMessageBox::critical(this, "错误", "数据表查询错误,错误信息\n"+qryModel->lastError().text());return;}//2. 设置字段显示标题QSqlRecord rec=qryModel->record();  //获取一个空记录,为了获取字段序号qryModel->setHeaderData(rec.indexOf("empNo"),  Qt::Horizontal, "工号");qryModel->setHeaderData(rec.indexOf("Name"),   Qt::Horizontal, "姓名");qryModel->setHeaderData(rec.indexOf("Gender"), Qt::Horizontal, "性别");qryModel->setHeaderData(rec.indexOf("Birthday"),   Qt::Horizontal, "出生日期");qryModel->setHeaderData(rec.indexOf("Province"),   Qt::Horizontal, "省份");qryModel->setHeaderData(rec.indexOf("Department"), Qt::Horizontal, "部门");qryModel->setHeaderData(rec.indexOf("Salary"),     Qt::Horizontal, "工资");//3. 创建选择模型selModel=new QItemSelectionModel(qryModel,this);connect(selModel,&QItemSelectionModel::currentRowChanged,this, &MainWindow::do_currentRowChanged);ui->tableView->setModel(qryModel);//4. 创建数据映射dataMapper= new QDataWidgetMapper(this);dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);dataMapper->setModel(qryModel);//界面组件与数据模型的具体字段之间的映射dataMapper->addMapping(ui->dbSpinEmpNo, rec.indexOf("empNo"));dataMapper->addMapping(ui->dbEditName,  rec.indexOf("Name"));dataMapper->addMapping(ui->dbComboSex,  rec.indexOf("Gender"));dataMapper->addMapping(ui->dbEditBirth, rec.indexOf("Birthday"));dataMapper->addMapping(ui->dbComboProvince, rec.indexOf("Province"));dataMapper->addMapping(ui->dbComboDep,      rec.indexOf("Department"));dataMapper->addMapping(ui->dbSpinSalary,    rec.indexOf("Salary"));dataMapper->toFirst();  //移动到首记录

record函数不带参数可以获取字段名称,想要获取对应记录的字段对应值,可以参考以下:

    QSqlRecord rec1=qryModel->record(2);QVariant vr = rec1.value("Name");QString qs = vr.toString();qDebug() << qs;

使用ui->tableView->setSelectionModel(selModel);语句将界面显示与模型绑定在一起。

dataMapper将UI中的一系列界面组件映射到一条记录的不同字段,便设置显示为第一条记录的数据内容。

ui->tableView->setSelectionModel(selModel);设置了选择模型,当选择的行发生改变时候会进入以下槽函数:

void MainWindow::do_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{Q_UNUSED(previous);if (!current.isValid()){ui->dbLabPhoto->clear();ui->dbEditMemo->clear();return;}dataMapper->setCurrentModelIndex(current);      //设置当前行//    dataMapper->setCurrentIndex(current.row());   //这个也可以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=selModel->currentIndex().row();QSqlRecord  curRec=qryModel->record(curRecNo);  //获取当前记录int empNo=curRec.value("EmpNo").toInt();    //主键字段QSqlQuery query(DB);    //查询某个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());
}

在槽函数中获取当前选择的记录,并设置dataMapper,选择的记录条在其他组件中同步更新,获取该记录的一些数据,然后用一个 QSqlQuery 变量 query 运行查询语句,查询对应EmpNo号对应记录的BLOB类型数据,并转化显示为图片。

记录的移动需要根据 QDataWidgetMapper 对象的当前行设置选择模型的当前行,这样才能使

QTableView组件和数据感知组件的当前行是同步的。


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();
}//刷新tableView的当前行
void MainWindow::refreshTableView()
{int index=dataMapper->currentIndex();   //dataMapper的当前行号QModelIndex curIndex=qryModel->index(index,1);  //为当前行创建模型索引selModel->clearSelection();         //清空选择项selModel->setCurrentIndex(curIndex,QItemSelectionModel::Select);    //设置当前行
}


http://www.mrgr.cn/news/80071.html

相关文章:

  • 《Python WEB安全 库全攻略》
  • 14:00面试,14:08就出来了,问的问题有点变态。。。
  • C++ webrtc开发(非原生开发,linux上使用libdatachannel库)
  • 暴雨首发 Turin平台服务器亮相中国解决方案AMD峰会巡展
  • 蓝桥题库:编号2094--推导部分和(并查集+搜索)
  • 手机实时提取SIM卡打电话的信令声音--社会价值(一、方案解决了什么问题)
  • Unity 制作一个视频播放器(打包后,可在外部编辑并放置新的视频)
  • 动手学深度学习---预备知识
  • 软考高级架构 —— 10.6 大型网站系统架构演化实例 + 软件架构维护
  • 【rust杂乱笔记】
  • 20.LMAX——DDD的极致性能架构
  • 前端常用的方法
  • Electron electron-builder.yml 配置 (自定义包名,用户自定义安装目录...)
  • flink sink kafka的事务提交现象猜想
  • avue-crud 同时使用 column 与 group 的问题
  • 2024前端面试题(持续更新)
  • 力扣题目 - 935. 骑士拨号器
  • 【汇编】思考汇编中的两个基本问题
  • STM32F407+LAN8720A +LWIP +FreeRTOS ping通
  • c# 协变与抗变
  • 蓝桥杯我来了
  • 【1211更新】腾讯混元Hunyuan3D-1文/图生3D模型云端镜像一键运行
  • 微服务篇面试题
  • 案例讲解自然语言处理(NLP)
  • 【从零开始入门unity游戏开发之——C#篇03】变量和常量
  • SpringBoot3集成MybatisPlus3和knife4j(swagger3兼容增强版)