本文记录QSqlQueryModel的使用过程。
QSqlQueryModel
QSqlQueryModel是一个模型类,它可以设置任意的SELECT语句从数据库中查询数据。QSqlQueryModel模型的数据是只读的,即使在界面上修改了QSqlQueryModel模型的数据,也不能将所做的修改提交到数据库。
目录
给qryModel设置选择模型,选择模型的行变化事件绑定到执行方法
声明类
QSqlQueryModel *qryModel;//查询数据库模型
QItemSelectionModel *selModel;//选择数据模型
QDataWidgetMapper *dataMapper;//数据与界面映射组件
QStringList genderList;//性别 列表
QStringList deptList;//部门列表
QStringList provinceList;//省份列表
SQLiteHelper dbHelper;//自定义数据库帮助类
执行表查询
创建数据模型
qryModel = new QSqlQueryModel(this);
查询
qryModel->setQuery("SELECT empNo, Name, Gender, Birthday, Province, Department, "
" Salary FROM employee ORDER BY empNo");
if(qryModel->lastError().isValid())
{
QMessageBox::critical(this,"错误","数据表查询错误,错误信息\n"+qryModel->lastError().text());
return;
}
显示条数
ui->statusbar->showMessage(QString("记录数:%1").arg(qryModel->rowCount()));
设置表格列的水平标题
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, "工资");
给qryModel设置选择模型,选择模型的行变化事件绑定到执行方法
selModel = new QItemSelectionModel(qryModel,this); //给qryModel设置选择模型
connect(selModel,&QItemSelectionModel::currentRowChanged,this,&SqlQueryModelExample::do_currentRowChanged);
给tabView设置数据模型、设置选择模型
ui->tableView->setModel(qryModel);
ui->tableView->setSelectionModel(selModel);
声明数据界面组件,并给数据界面组件绑定数据Model
dataMapper = new QDataWidgetMapper(this);
dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
dataMapper->setModel(qryModel);
建立数据模型字段与界面组件之间的绑定
//建立界面组件和model字段之间的映射
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->dbComboDept, rec.indexOf("Department"));
dataMapper->addMapping(ui->dbSpinSalary, rec.indexOf("Salary"));
dataMapper->toFirst();
事件
窗体界面初始化
给tableView初始化设置
tableView 只读,行选择,行颜色交替变化,单个选择模式。行选择模式下,单个指的是单行选择。
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);//不能编辑
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);//行选择模式
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);//单个选择模式,这里是单行
ui->tableView->setAlternatingRowColors(true);//行交替颜色变化
QItemSelectionView选择模型的行变化
根据行号,判断按钮的使能状态
dataMapper->setCurrentIndex(current.row());
bool isFirst = (current.row()==0);
bool isLast = (current.row()== qryModel->rowCount()-1);
ui->actRecFirst->setEnabled(!isFirst);//当前为首行,首行按钮灰掉
ui->actRecPrevious->setEnabled(!isFirst);//当前为首行,上一条按钮灰掉
ui->actRecLast->setEnabled(!isLast);//当前为末行,末行按钮灰掉
ui->actRecNext->setEnabled(!isLast);//当前为末行,下一行按钮灰掉
执行单行查询
使用QSqlQuery ,参数化sql数据,传入:ID参数,执行查询,将获取的ByteArray 载入到界面图片,将memo长文本加载显示
int curRecNo = selModel->currentIndex().row();
QSqlRecord curRec = qryModel->record(curRecNo);
int empNo = curRec.value("empNo").toInt();
QSqlQuery query;
query.prepare("SELECT empNo,Photo,Memo 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());
跳转首行、末行、下一行、上一行
行标切换,用到数据界面组件的,toFirst(),toLast() 、toPrevious()、toNext() 方法,类似于游标。
dataMapper->toFirst();
//dataMapper->toPrevious();
//dataMapper->toNext();
//dataMapper->toLast();
refreshTableView();
刷新界面选择模型的选中
先取到dataMapper的当前索引号,转换为 数据模型的 索引,然后将选择模型定位到该数据模型的索引。
void SqlQueryModelExample::refreshTableView()
{
int index = dataMapper->currentIndex();
QModelIndex curIndex = qryModel->index(index,1);
selModel->clearSelection();
selModel->setCurrentIndex(curIndex,QItemSelectionModel::Select);
}
总结
1. 移动行的过程中,使用的dataMapper的toFirst/Last/Previous/Next方法,移动时加载了界面中控件绑定的数据模型的字段值。
2. 获取dataMapper的索引号,得到qryModel的索引号,再得到selModel的索引号,然后selModel定位选中到该索引。
3. selModel的行定位发生变化,导致执行事件currentRowChanged,从而加载ByteArray Blob存储的图片,和长文本的memo字段。