QSqlQueryModel 是 QSqlTableModel 的父类。QSqlQueryModel 封装了执行 SELECT 语句从数据库查询数据的功能,但
是 QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据 。
这个界面布局跟 QSqlTableModel 的布局是一样的,需要看到话,可以在我博客了找下。
老规矩:
工程文件:
QT += sql
对应的头文件:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
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:
// void on_primeInsert(int row, QSqlRecord &record);//插入记录时,用于设置缺省字段数据
// void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
// QTableView的SelectionModel的行发生了变化,进行处理
void on_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
///////////////////////
void on_actOpenDB_triggered();
// void on_actPhoto_triggered();
// void on_actPhotoClear_triggered();
void on_actRecFirst_triggered();
void on_actRecPrevious_triggered();
void on_actRecNext_triggered();
void on_actRecLast_triggered();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
cpp代码解析部分:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
LabInfo=new QLabel("记录条数",this);
LabInfo->setMinimumWidth(200);
ui->statusBar->addWidget(LabInfo);
this->setCentralWidget(ui->splitter);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView->setAlternatingRowColors(true);
// ui->tableView->resizeColumnsToContents();
// ui->tableView->horizontalHeader()->setStretchLastSection(true);
}
基本记录了文件状态栏的,还有tableview 的属性
void MainWindow::on_actOpenDB_triggered()
{//打开数据库
QString aFile=QFileDialog::getOpenFileName(this,"选择数据库文件","",
"SQL Lite数据库(*.db *.db3)");
if (aFile.isEmpty())
return;
//打开数据库
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);
return;
}
//打开数据表
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,"工资");
// qryModel->setHeaderData(11,Qt::Horizontal,"照片");
// qryModel->setHeaderData(12,Qt::Horizontal,"备注");
theSelection=new QItemSelectionModel(qryModel);
//选择行变化时
connect(theSelection,SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
this,SLOT(on_currentRowChanged(QModelIndex,QModelIndex)));
// connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),
// this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));
ui->tableView->setModel(qryModel);
ui->tableView->setSelectionModel(theSelection);
// ui->tableView->setColumnHidden(11,true);//"照片",隐藏列
// ui->tableView->setColumnHidden(12,true);//"备注",隐藏列
// ui->tableView->resizeColumnsToContents();
// ui->tableView->horizontalHeader()->setStretchLastSection(true);
//创建数据映射
dataMapper= new QDataWidgetMapper();
dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
dataMapper->setModel(qryModel);
// dataMapper->setItemDelegate(new QSqlRelationalDelegate(this)); //含有外键的
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->addMapping(ui->dbEditMemo,tabModel->fieldIndex("Memo"));
// dataMapper->addMapping(ui->dbPhoto,tabModel->fieldIndex("Photo")); //图片无法直接映射
dataMapper->toFirst();
ui->actOpenDB->setEnabled(false);
// ui->actRecAppend->setEnabled(true);
// ui->actRecInsert->setEnabled(true);
// ui->actRecDelete->setEnabled(true);
// ui->actScan->setEnabled(true);
}
程序首先创建了 QSqlQueryModel 类型的私有变量 qryModel ,然后调用 setQuery() 函数设置了SELECT 查询语句, SELECT 语句从 employe巳表里查询除了 Memo 和 Photo 之外的所有其他字段。
使用 setHeaderData()函数为每个字段设置显示标题,为使代码简化,这里直接使用了宇段的序号。为 qryMode l 创建了边择模型 theSelection ,并且将其 currentRowChanged()信号与自定义槽函数 on_currentRowChanged()关联起来 。这个自定义槽函数用来在记录移动时 , 查询出 Memo 和 Photo字段的内容,并在界面上显示出来 。
void MainWindow::on_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
Q_UNUSED(previous);
if (!current.isValid())
{
ui->dbLabPhoto->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);
// QModelIndex curIndex=theSelection->currentIndex();//获取当前选择单元格的模型索引
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());
}
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();
}
void MainWindow::refreshTableView()
{//刷新tableView的当前选择行
int index=dataMapper->currentIndex();
QModelIndex curIndex=qryModel->index(index,1);//
theSelection->clearSelection();//清空选择项
theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//设置刚插入的行为当前选择行
}
本文例子的连接:
链接:https://pan.baidu.com/s/1iMqXLQCVLqPr0luiKleHEA 提取码:fy14
喜欢的可以关注我博客,更多惊喜等你哟。