数据库毗连、数据模子与界面组件所涉及的类之间的关系如下所示:
数据库类
QSqlDatabase 类用于创建与数据库的毗连,QSqlDatabase 对象就体现这种毗连。QSqlDatabase 类的功能重要分为三大部门:
1、创建数据库毗连,即创建 QSqlDatabase 对象,加载指定范例的数据库驱动。
静态函数 QSqlDatabase::addDatabase()创建 QSqlDatabase 对象:
QSqlDatabase QSqlDatabase::addDatabase(const QString &type,
const QString &connectionName = QLatin1String(defaultConnection))
参数 type 是要毗连的数据库范例:
如“QSQLITE”就是指 SQLite 数据库,参数 connectionName 是所创建的数据库毗连的名称,如
果不设置这个参数,就采取应用步调默认的数据库毗连。利用函数 addDatabase()创建 QSqlDatabase 对象时只是设置了驱动步调名称,设置的 connection Name 会被自动添加到应用步调的数据库毗连名称列表。假如乐成创建 QSqlDatabase 对象,QSqlDatabase 的函数 isValid()会返回 true。一个 QSqlDatabase 对象用于体现一个数据库毗连,一个应用步调里可以创建多个 QSqlDatabase 对象,它们可分别毗连一个数据库。利用静态函数 QSqlDatabase::connectionNames()返回应用步调里全部已 创建的数据库毗连名称列表。假如一个应用步调里有多个数据库毗连,可以利用静态函数 QSqlDatabase::database()通过 connectionName 来引用此中的某个数据库毗连。
2、打开数据库,设置必要毗连的数据库详细参数,比方数据库名称、用户名、用户暗码等,
然后打开数据库。只有打开数据库之后,才可以举行数据查询和修改等利用。
运行函数 QSqlDatabase::addDatabase()只是加载了数据库驱动,创建了数据 库毗连,还必要用 QSqlDatabase 的函数 open()打开一个详细的数据库。设置好毗连数据库参数后,用函数 open()打开数据库,假如 open()的返回值为 true,体现乐成打开数据库。若要关闭数据库,则要利用函数 close()。
3、对数据库举行事件(transaction)利用,获取数据库的一些信息。- bool MainWindow::openDatabase(QString aFile)
- {
- DB=QSqlDatabase::addDatabase("QSQLITE","Database1"); //添加 SQLITE数据库驱动
- DB.setDatabaseName(aFile); //设置数据库名称
- if (!DB.open()) //打开数据库失败
- return false;
- else
- {
- openTable(); //打开数据表
- return true;
- }
- }
复制代码 QSqlTableModel 是一个模子类,它与数据库中的一个数据表关联后就作为该数据表的模子。
QSqlTableModel 类的构造函数界说如下:
QSqlTableModel(QObject *parent = nullptr, const QSqlDatabase &db = QSqlDatabase())
创建 QSqlTableModel 对象时必要指定命据库毗连,也就是设置一个 QSqlDatabase 对象。假如
不指定命据库毗连,就利用应用步调的默认数据库毗连。还必要利用 QSqlTableModel 的 setTable()函数设置必要毗连的数据表。
函数 select()。这个函数的作用是根据当前设置的排序和过滤规则从数据表查询数据并将 其革新到数据模子。在利用函数 setTable()设置数据表之后,还必要运行函数 select()才华将数据刷 新到模子。函数 select()的返回值若为 true,则体现数据查询利用乐成;若为 false,则体现利用失 败,可以通过函数 lastError()获取错误信息。- tabModel=new QSqlTableModel(this,DB); //数据模型
- tabModel->setTable("employee"); //设置数据表
- tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit); //数据保存方式,OnManualSubmit , OnRowChange
- tabModel->setSort(tabModel->fieldIndex("empNo"),Qt::AscendingOrder); //排序
- if (!(tabModel->select())) //查询数据失败
- {
- QMessageBox::critical(this, "错误信息",
- "打开数据表错误,错误信息:\n"+tabModel->lastError().text());
- return;
- }
复制代码 创建View组件与model的模子/视图
为一个 QTableView 组件设置一个 QSqlTableModel 模子后,它们就构成模子/视图结构,可以
体现和编辑数据表的数据。还可以为 QSqlTableModel 模子设置一个 QItemSelectionModel 对象作
为选择模子。在 QTableView 组件中可以利用自界说署理。- //Model/View结构
- ui->tableView->setModel(tabModel); //设置数据模型
- selModel=new QItemSelectionModel(tabModel,this); //关联选择模型
- ui->tableView->setSelectionModel(selModel); //设置选择模型
复制代码 创建界面组件与Model的映射
QDataWidgetMapper 类对象要设置一个 QSqlTableModel 模子,然后将数据表的某个字段与界面
上某个组件创建映射,界面组件就可以自动体现这个字段的数据,成为数据感知(data-aware)组件。如许这些界面组件就会自动体现关联字段的数据,而且在组件中修改数据后可以提交到模子。
一样平常的数值、字符串、备注等范例的字段可以用 QSpinBox、QLineEdit、QPlainTextEdit 等界
面组件作为数据感知组件,但是 BLOB 范例的字段不能直接与某个界面组件创建映射。如图片数据信息,必要单独编写代码实现图片的体现、导入和打扫等利用。
QDataWidgetMapper::AutoSubmit:自动提交。当一个界面组件失去输入核心时,所举行的
修改自动提交到模子。
QDataWidgetMapper 对象指向数据模子的某一行记录并将其作为当前行,函数 currentIndex()
返回当前行号,函数 setCurrentIndex()可以设置当前行号,toFirst()、toPrevious()、toNext()和 toLast() 函数可以移动当前行。QDataWidgetMapper 对象的当前行厘革时,设置了映射字段的界面组件会 自动更新体现当前记录的数据- //创建界面组件与数据模型的字段之间的数据映射
- dataMapper= new QDataWidgetMapper(this);
- dataMapper->setModel(tabModel); //设置数据模型
- dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit); //数据更新方式
- //界面组件与数据模型的具体字段之间的联系
- dataMapper->addMapping(ui->dbSpinEmpNo,tabModel->fieldIndex("empNo"));
- dataMapper->addMapping(ui->dbEditName,tabModel->fieldIndex("Name"));
- dataMapper->addMapping(ui->dbComboSex,tabModel->fieldIndex("Gender"));
- dataMapper->addMapping(ui->dbEditBirth,tabModel->fieldIndex("Birthday"));
- dataMapper->addMapping(ui->dbComboProvince,tabModel->fieldIndex("Province"));
- dataMapper->addMapping(ui->dbComboDep,tabModel->fieldIndex("Department"));
- dataMapper->addMapping(ui->dbSpinSalary,tabModel->fieldIndex("Salary"));
- dataMapper->addMapping(ui->dbEditMemo,tabModel->fieldIndex("Memo"));
- dataMapper->toFirst(); //移动到首记录
复制代码 界面的数据表格上点击 单位格,使数据模子 tabModel 的当前记录发生厘革时,dataMapper 的当前行并不会自动厘革。因此假如要确保视图组件 tableView 中的当前行和数据映射对象 dataMapper 的当前行是同等,在修改currentIndex发生厘革时间,必要利用以下来更新- dataMapper->setCurrentIndex(current.row()); //更新数据映射的行号
复制代码 设置字段体现的标题
函数 fieldIndex()。这个函数根据字段名称返回字段的序号。若字段不存在,则返回-1。利用时注意要与数据库的表格字段同等,以防找不到字段
函数 setHeaderData()。这个函数用于设置一个字段的表头数据,一样平常用于设置字段的体现标题。
bool QSqlQueryModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole)
此中,section 是字段序号;orientation 是方向,对于字段就是 Qt::Horizontal;value 是必要设置的数据;role 是数据的脚色,默以为 Qt::EditRole。假如不举行表头设置,在 QTableView 组件里体现表格数据时,会将字段名作为表头。- tabModel->setHeaderData(tabModel->fieldIndex("empNo"), Qt::Horizontal, "工号");
- tabModel->setHeaderData(tabModel->fieldIndex("Name"), Qt::Horizontal, "姓名");
- tabModel->setHeaderData(tabModel->fieldIndex("Gender"), Qt::Horizontal, "性别");
- tabModel->setHeaderData(tabModel->fieldIndex("Birthday"), Qt::Horizontal, "出生日期");
- tabModel->setHeaderData(tabModel->fieldIndex("Province"), Qt::Horizontal, "省份");
- tabModel->setHeaderData(tabModel->fieldIndex("Department"), Qt::Horizontal, "部门");
- tabModel->setHeaderData(tabModel->fieldIndex("Salary"), Qt::Horizontal, "工资");
- tabModel->setHeaderData(tabModel->fieldIndex("Memo"),Qt::Horizontal,"备注");
- tabModel->setHeaderData(tabModel->fieldIndex("Photo"),Qt::Horizontal,"照片");
复制代码 获取记录的字段
QSqlRecord 类记录了数据表的字段信息和一条记录的数据内容,QSqlTableModel 有两种参数
情势的函数 record()可以返回一条记录。
QSqlRecord QSqlTableModel::record() //返回字段界说
QSqlRecord QSqlTableModel::record(int row) //返回字段界说和数据
不带有参数的函数 record()返回的一个 QSqlRecord 对象只有记录的字段界说,没有各字段的
数据,一样平常用于获取一个数据表的字段界说。带有参数的函数 record()返回行号为 row 的记录,包罗记录的字段界说和数据。- //获取所有字段名称
- void MainWindow::getFieldNames()
- {
- QSqlRecord emptyRec=tabModel->record(); //获取空记录,只有字段名
- for (int i=0;i<emptyRec.count();i++)
- ui->comboFields->addItem(emptyRec.fieldName(i));
- }
复制代码 添加-修改-插入-删除项
insertRecord() 用于添加或插入记录,函数 setRecord()用于修改记录,删除记录利用的是函数 removeRow()。
在插入记录时,纵然是必填字段(比方 Name 字段)没有被赋值,步调也不会堕落,由于我们设置的数据模子 tabModel 的编辑计谋是 OnManualSubmit。但是在生存修改到数据库时,假如必填字段没有设置数据,则会出现错误。- void MainWindow::on_actRecAppend_triggered()
- {//添加一条记录
- //// 使用QSqlRecord
- QSqlRecord rec=tabModel->record(); //获取一个空记录,只有字段定义
- rec.setValue(tabModel->fieldIndex("empNo"),2000+tabModel->rowCount());
- rec.setValue(tabModel->fieldIndex("Gender"),"男"); //设置数据
- tabModel->insertRecord(tabModel->rowCount(),rec); //插入到数据模型的最后
- selModel->clearSelection();
- QModelIndex curIndex=tabModel->index(tabModel->rowCount()-1,1); //创建最后一行的ModelIndex
- selModel->setCurrentIndex(curIndex,QItemSelectionModel::Select);
- showRecordCount();
- ////项数据模型操作方式,功能相同,但是不符合数据库的操作习惯
- // tabModel->insertRow(tabModel->rowCount(),QModelIndex()); //在末尾添加一行
- // QModelIndex curIndex=tabModel->index(tabModel->rowCount()-1,1); //创建最后一行的ModelIndex
- // theSelection->clearSelection(); //清空选择项
- // theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select); //设置刚插入的行为当前行
- // int currow=curIndex.row(); //获得当前行编号
- // tabModel->setData(tabModel->index(currow,tabModel->fieldIndex("empNo")),
- // 2000+tabModel->rowCount()); //自动生成编号
- // tabModel->setData(tabModel->index(currow,tabModel->fieldIndex("Gender")),"男"); //必填字段,需要赋值
- // showRecordCount();
- // 插入行时设置缺省值,需要在primeInsert()信号里去处理
- }
- void MainWindow::on_actRecInsert_triggered()
- {//插入一条记录
- //// 使用QSqlRecord
- QModelIndex curIndex=ui->tableView->currentIndex();
- QSqlRecord rec=tabModel->record(); //获取一个空记录,只有字段定义
- tabModel->insertRecord(curIndex.row(),rec); //在当前行前面插入一条记录
- selModel->clearSelection();
- selModel->setCurrentIndex(curIndex,QItemSelectionModel::Select); //设置当前行
- showRecordCount();
- //项数据模型操作方式,功能相同,但是不符合数据库的操作习惯
- // QModelIndex curIndex=ui->tableView->currentIndex(); //当前行的模型索引
- // tabModel->insertRow(curIndex.row(),QModelIndex()); //插入一行
- // theSelection->clearSelection(); //清除已有选择
- // theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select); //选择新插入的一行
- // showRecordCount();
- }
- void MainWindow::on_actRecDelete_triggered()
- {//删除当前记录
- QModelIndex curIndex=selModel->currentIndex(); //获取当前选择单元格的模型索引
- tabModel->removeRow(curIndex.row()); //删除当前行
- showRecordCount();
- }
复制代码 生存或取消修改
数据模子 tabModel 的编辑计谋为 OnManualSubmit时,即手动提交 修改。当数据模子的数据被修改后,不管是直接修改字段值,还是插入或删除记录,在未提交修改前, tabModel->isDirty()函数都返回 true。生存会将全部对Model举行的增编削同步到数据库.db文件中,取消会打消对model的增编削利用。
函数 submitAll()用于将数据模子全部未提交的修改生存到数据库,函数 revertAll()取消全部修
改。调用 submitAll()生存数据时假如失败,可以通过函数 lastError()获取错误的详细信息。- void MainWindow::on_actRevert_triggered()
- {//取消修改
- tabModel->revertAll();
- ui->actSubmit->setEnabled(false);
- ui->actRevert->setEnabled(false);
- showRecordCount();
- }
- void MainWindow::on_actSubmit_triggered()
- {//保存修改
- bool res=tabModel->submitAll();
- if (!res)
- QMessageBox::information(this, "消息", "数据保存错误,错误信息\n"+tabModel->lastError().text());
- else
- {
- ui->actSubmit->setEnabled(false);
- ui->actRevert->setEnabled(false);
- }
- showRecordCount();
- }
复制代码 遍历数据记录
获取model的count后,利用record(i)即可遍历每一条记录,通过value函数访问每个字段对应的数据,便可遍历修改后生存。- void MainWindow::on_actScan_triggered()
- {//涨工资,记录遍历
- if (tabModel->rowCount()==0)
- return;
- for (int i=0;i<tabModel->rowCount();i++)
- {
- QSqlRecord aRec=tabModel->record(i); //获取一条记录
- float salary=aRec.value("Salary").toFloat();
- salary=salary*1.1;
- aRec.setValue("Salary",salary); //更新记录数据
- tabModel->setRecord(i,aRec); //更新记录
- }
- // 索引方式刷新记录,速度一样
- // float salary;
- // for (int i=0;i<tabModel->rowCount();i++)
- // {
- // salary=tabModel->data(tabModel->index(i,10)).toFloat();
- // salary=salary*1.1;
- // tabModel->setData(tabModel->index(i,10),salary);
- // }
- if (tabModel->submitAll())
- QMessageBox::information(this, "消息", "涨工资数据计算完毕");
- }
复制代码 记录排序
QSqlTableModel 模子里的记录可以按某个字段排序,对应 SQL 语句中的 ORDER BY 子句。
QSqlTableModel 有 setSort()和 sort()两个函数用于排序。
void QSqlTableModel::setSort(int column, Qt::SortOrder order) //设置排序条件
void QSqlTableModel::sort(int column, Qt::SortOrder order) //立刻排序
参数 column 体现排序字段的字段序号;参数 order 体现排序方式,可设置为升序(Qt::Ascending
Order)或降序(Qt: escendingOrder)。
这两个函数稍有差别,函数 setSort()只是用于设置排序条件,必要再运行 select()函数才会刷
新数据模子的数据;函数 sort()则是用于根据设置的字段和排序方式直接排序并革新数据模子,无
须调用 select()函数。- void MainWindow::on_comboFields_currentIndexChanged(int index)
- {//选择字段进行排序
- if (ui->radioBtnAscend->isChecked())
- tabModel->setSort(index,Qt::AscendingOrder);
- else
- tabModel->setSort(index,Qt::DescendingOrder);
- tabModel->select();
- }
- void MainWindow::on_radioBtnAscend_clicked()
- {//升序排序
- tabModel->setSort(ui->comboFields->currentIndex(),Qt::AscendingOrder);
- tabModel->select(); //setSort()之后需要执行select()才会刷新数据
- }
- void MainWindow::on_radioBtnDescend_clicked()
- {//降序排序
- tabModel->sort(ui->comboFields->currentIndex(),Qt::DescendingOrder);
- // tabModel->setSort(ui->comboFields->currentIndex(),Qt::DescendingOrder);
- // tabModel->select();
- }
复制代码 记录过滤
QSqlTableModel 的 setFilter()函数可设置记录过滤条件,该函数原型界说如下:
void QSqlTableModel::setFilter(const QString &filter)
字符串范例的参数 filter 是过滤条件,实际上就是 SELECT 语句里 WHERE 子句的条件。
运行 setFilter()函数后无须调用 select()函数就可以立刻革新记录,若要取消过滤,只需在
setFilter()函数里转达一个空字符串。- void MainWindow::on_radioBtnMan_clicked()
- {
- tabModel->setFilter(" Gender='男' ");
- showRecordCount();
- }
- void MainWindow::on_radioBtnWoman_clicked()
- {
- tabModel->setFilter(" Gender='女' ");
- showRecordCount();
- }
- void MainWindow::on_radioBtnBoth_clicked()
- {
- tabModel->setFilter("");
- showRecordCount();
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |