QTabelModel的好处就是不需要执行sql语句就可以对数据库进行操作。
创建数据库:
QSqlDatabase DB;//数据库连接
QString aFile=QFileDialog::getOpenFileName(this,"选择数据库文件","",
"SQL Lite数据库(*.db *.db3)");
DB=QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动
DB.setDatabaseName(aFile); //设置数据库名称
// DB.setHostName();
// DB.setUserName();
// DB.setPassword();
if (!DB.open()) //打开数据库
{
QMessageBox::warning(this, "错误", "打开数据库失败",
QMessageBox::Ok,QMessageBox::NoButton);
创建模型:
QSqlTableModel *tabModel; //数据模型
tabModel=new QSqlTableModel(this,DB);//数据表
设置要打开哪张表:
tabModel->setTable("employee"); //设置要打开的数据表
设置数据保存的条件:
tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);//数据保存方式,OnManualSubmit , OnRowChange
设置数据显示的时候排序的条件:
tabModel->setSort(tabModel->fieldIndex("empNo"),Qt::AscendingOrder); //排序
判断打开数据表是否成功:
tabModel->select()
将数据库每个字段的名称与模型对应视图应该现实的名称对应起来:
//字段显示名
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("Height"),Qt::Horizontal,"身高");
tabModel->setHeaderData(tabModel->fieldIndex("Birthday"),Qt::Horizontal,"出生日期");
tabModel->setHeaderData(tabModel->fieldIndex("Mobile"),Qt::Horizontal,"手机");
tabModel->setHeaderData(tabModel->fieldIndex("Province"),Qt::Horizontal,"省份");
tabModel->setHeaderData(tabModel->fieldIndex("City"),Qt::Horizontal,"城市");
tabModel->setHeaderData(tabModel->fieldIndex("Department"),Qt::Horizontal,"部门");
tabModel->setHeaderData(tabModel->fieldIndex("Education"),Qt::Horizontal,"学历");
tabModel->setHeaderData(tabModel->fieldIndex("Salary"),Qt::Horizontal,"工资");
tabModel->setHeaderData(tabModel->fieldIndex("Memo"),Qt::Horizontal,"备注"); //这两个字段不再tableView中显示
tabModel->setHeaderData(tabModel->fieldIndex("Photo"),Qt::Horizontal,"照片");
创建选择模型并进行关联:
QItemSelectionModel *theSelection; //选择模型
theSelection=new QItemSelectionModel(tabModel);//关联选择模型
连接两个槽函数:
//theSelection当前项变化时触发currentChanged信号
connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),
this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));
//选择行变化时
connect(theSelection,SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
this,SLOT(on_currentRowChanged(QModelIndex,QModelIndex)));
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{//更新actPost和actCancel 的状态
Q_UNUSED(current);
Q_UNUSED(previous);
ui->actSubmit->setEnabled(tabModel->isDirty()); //有未保存修改时可用
ui->actRevert->setEnabled(tabModel->isDirty());
}
void MainWindow::on_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
Q_UNUSED(previous);
// 行切换时的状态控制
ui->actRecDelete->setEnabled(current.isValid());
ui->actPhoto->setEnabled(current.isValid());
ui->actPhotoClear->setEnabled(current.isValid());
if (!current.isValid())
{
ui->dbLabPhoto->clear(); //清除图片显示
return;
}
dataMapper->setCurrentIndex(current.row()); //更新数据映射的行号
int curRecNo=current.row();//获取行号
QSqlRecord curRec=tabModel->record(curRecNo); //获取当前记录,改记录就是数据库中的一条数据,传递行号即可
if (curRec.isNull("Photo")) //图片字段内容为空
ui->dbLabPhoto->clear();
else
{
QByteArray data=curRec.value("Photo").toByteArray();
QPixmap pic;
pic.loadFromData(data);
ui->dbLabPhoto->setPixmap(pic.scaledToWidth(ui->dbLabPhoto->size().width()));
}
}
将模型和视图进行绑定并设置不显示列:
ui->tableView->setModel(tabModel);//设置数据模型
ui->tableView->setSelectionModel(theSelection); //设置选择模型
ui->tableView->setColumnHidden(tabModel->fieldIndex("Memo"),true);//隐藏列,即不显示这列
ui->tableView->setColumnHidden(tabModel->fieldIndex("Photo"),true);//隐藏列,即不显示这列
为某些列指定代理组件,主要用于需要进行编辑的列:
//tableView上为“性别”和“部门”两个字段设置自定义代理组件
QStringList strList;
strList<<"男"<<"女";
bool isEditable=false;
delegateSex.setItems(strList,isEditable);
ui->tableView->setItemDelegateForColumn(
tabModel->fieldIndex("Gender"),&delegateSex); //Combbox选择型
strList.clear();
strList<<"销售部"<<"技术部"<<"生产部"<<"行政部";
isEditable=true;
delegateDepart.setItems(strList,isEditable);
ui->tableView->setItemDelegateForColumn(tabModel->fieldIndex("Department"),&delegateDepart); //Combbox选择型
创建界面组件与数据模型的字段之间的数据映射,这样就将界面上的各个编辑组件与对应字段的数据进行绑定:
QDataWidgetMapper *dataMapper; //数据映射
//创建界面组件与数据模型的字段之间的数据映射
dataMapper= new QDataWidgetMapper();
dataMapper->setModel(tabModel);//设置数据模型
dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);//
// dataMapper->setItemDelegate(new QSqlRelationalDelegate(this)); //含有外键的
//界面组件与tabModel的具体字段之间的联系
dataMapper->addMapping(ui->dbSpinEmpNo,tabModel->fieldIndex("empNo"));
dataMapper->addMapping(ui->dbEditName,tabModel->fieldIndex("Name"));
dataMapper->addMapping(ui->dbComboSex,tabModel->fieldIndex("Gender"));
dataMapper->addMapping(ui->dbSpinHeight,tabModel->fieldIndex("Height"));
dataMapper->addMapping(ui->dbEditBirth,tabModel->fieldIndex("Birthday"));
dataMapper->addMapping(ui->dbEditMobile,tabModel->fieldIndex("Mobile"));
dataMapper->addMapping(ui->dbComboProvince,tabModel->fieldIndex("Province"));
dataMapper->addMapping(ui->dbEditCity,tabModel->fieldIndex("City"));
dataMapper->addMapping(ui->dbComboDep,tabModel->fieldIndex("Department"));
dataMapper->addMapping(ui->dbComboEdu,tabModel->fieldIndex("Education"));
dataMapper->addMapping(ui->dbSpinSalary,tabModel->fieldIndex("Salary"));
dataMapper->addMapping(ui->dbEditMemo,tabModel->fieldIndex("Memo"));
// dataMapper->addMapping(ui->dbPhoto,tabModel->fieldIndex("Photo")); //图片无法直接映射
dataMapper->toFirst();//移动到首记录
创建数据记录QSqlRecord:
//获取所有字段名称进行填充
QSqlRecord emptyRec=tabModel->record();//获取空记录,只有字段名
for (int i=0;i<emptyRec.count();i++)
ui->comboFields->addItem(emptyRec.fieldName(i));
QSqlRecord rec(int row)返回的就是第row行记录
增删改查的操作:
void MainWindow::on_actRecAppend_triggered()
{//添加记录
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,0),2000+tabModel->rowCount()); //自动生成编号
tabModel->setData(tabModel->index(currow,2),"男");
// 插入行时设置缺省值,需要在primeInsert()信号里去处理
}
void MainWindow::on_actRecInsert_triggered()
{//插入记录
QModelIndex curIndex=ui->tableView->currentIndex();
tabModel->insertRow(curIndex.row(),QModelIndex());
theSelection->clearSelection();//清除已有选择
theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);
}
void MainWindow::on_actRevert_triggered()
{//取消修改
tabModel->revertAll();
ui->actSubmit->setEnabled(false);
ui->actRevert->setEnabled(false);
}
void MainWindow::on_actSubmit_triggered()
{//保存修改
bool res=tabModel->submitAll();
if (!res)
QMessageBox::information(this, "消息", "数据保存错误,错误信息\n"+tabModel->lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
else
{
ui->actSubmit->setEnabled(false);
ui->actRevert->setEnabled(false);
}
}
void MainWindow::on_actRecDelete_triggered()
{//删除当前记录
QModelIndex curIndex=theSelection->currentIndex();//获取当前选择单元格的模型索引
tabModel->removeRow(curIndex.row()); //删除最后一行
}
获取记录并设置记录的值:
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);
}
按设定的字段进行排序:
void MainWindow::on_comboFields_currentIndexChanged(int index)
{//选择字段进行排序
if (ui->radioBtnAscend->isChecked())
tabModel->setSort(index,Qt::AscendingOrder);
else
tabModel->setSort(index,Qt::DescendingOrder);
tabModel->select();
}