1、效果
2、添加 sql引用
.pro文件 添加 下面的引用
QT += sql
3、创建数据库链接
// 数据库连接
QSqlDatabase sqliteDatabase;
4、保存数据库连接
我使用了自定义数据库链接名
// 解除对数据库的默认连接
bool isContain = QSqlDatabase::contains(databaseConnectionName);
if (true == isContain)
{
sqliteDatabase = QSqlDatabase::database(databaseConnectionName);
}
else
{
sqliteDatabase = QSqlDatabase::addDatabase( "QSQLITE", databaseConnectionName);
}
使用SQLITE的数据库驱动如下:
sqliteDatabase = QSqlDatabase::addDatabase( "QSQLITE", databaseConnectionName);
其中, databaseConnectionName值如下
// 设置数据库连接名
databaseConnectionName = QString("helperConnection");
3、数据库的打开与关闭
// 2、检查数据库是否关闭
bool isOpen = sqliteDatabase.isOpen();
// 1.1 若已经打开数据库
if (true == isOpen)
{
// 1.1.1 关闭数据库
sqliteDatabase.close();
}
else
{
// 1.1.2 数据库没有打开
#ifdef QT_DEBUG
qDebug() << "数据库没有打开, 什么也不做";
#endif
}
4、指定数据库名
关联数据库文件 和 打开数据库
// 1、尝试打开新选择的文件,
sqliteDatabase.setDatabaseName(fileName);
// 1.1 尝试打开数据库
bool openFlag = sqliteDatabase.open();
// 1.2 若打开失败
if (false == openFlag)
{
QMessageBox::critical(this, tr("warning"), tr("open database file err"));
return;
}
取sqlite3数据库文件中的所有表名
// 2、读取数据库中的所有表名, 排除重复的表名 和 sqlite_sequence
QStringList tableNameList = sqliteDatabase.tables();
#ifdef QT_DEBUG
qDebug() << "查询的表名的个数= " << tableNameList.count();
#endif
///------------------------------------------------------------------
// 读取数据库中的表名
realTableName.clear();
int realTableNameCount = 0;
bool isFind = false;
foreach (QString name, tableNameList)
{
isFind = false;
// sqlite_sequence 排除
if ( QString("sqlite_sequence") == name)
{
continue;
}
realTableNameCount = realTableName.count();
// 若已经存在了,跳过
for (int i = 0; i < realTableNameCount; i++)
{
// 已经存在
if (name == realTableName.at(i))
{
isFind = true;
break;
}
}
// 若没找到, 说名name是唯一存在的, 则添加到数组
if (false == isFind)
{
// 若没有找到,则添加到列表中
realTableName << name;
}
}
数据库文件中,存在重复的表名, 代码中去掉了重复表名,同时排除了 表
sqlite_sequence
5、创建QSqlTableModel
声明
QSqlTableModel *sqlTableModel[he_tableview_count_10];
创建
for (int i = 0; i < he_tableview_count_10; i++)
{
sqlTableModel[i] = new QSqlTableModel(NULL, sqliteDatabase);
sqlTableModel[i]->setEditStrategy(QSqlTableModel::OnManualSubmit);
}
我用的是 QTableView 与 QSqlTableModel 关联 读写数据库, 每一个QSqlTableModel 对应一个 QTableView
6、使用QSqlTableModel
数据库打开后,即可使用model读取数据库数据了
// 3、读取数据库表中的数据,添加到tableView中显示
int sqlTableModelIndex = 0;
int index = 0;
foreach (QString name, realTableName)
{
QSqlTableModel *pModel = sqlTableModel[sqlTableModelIndex++];
// 设置连接的数据库名
pModel->setTable(name);
pModel->setSort(0, Qt::AscendingOrder);
// 设置手动提交
pModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
// 查询数据
pModel->select();
// 添加到tableview
tableViewArr[index]->setModel(pModel);
// 添加到tabwidget
tabWidget->addTab(tableViewArr[index], name);
// 设置tab
tabWidget->setTabIcon(index, QIcon(":/res/ico/tab/tab"));
// 解除对256行的限制
while(pModel->canFetchMore())
{
pModel->fetchMore();
}
// 计数器 +1
index += 1;
// 只显示第一张表的内容
if (1 == index)
{
break;
}
}
我这里做了限制, 只显示 数据库中的第一张表的内容, 去掉下面的代码,即可读取数据库中所有表的内容
// 只显示第一张表的内容
if (1 == index)
{
break;
}
QSqlTableModel, 若数据库表中的数据 超过 256行,则需要调用下面的代码解除对 256行的限制
// 解除对256行的限制
while(pModel->canFetchMore())
{
pModel->fetchMore();
}
7、关闭数据库
// 3、文件存在,判断是否打开
bool isOpen = sqliteDatabase.isOpen();
// 3.1 若没有打开
if (false == isOpen)
{
#ifdef QT_DEBUG
qDebug() << "数据库没有打开";
retVal = 0;
return retVal;
#endif
}
// 3.2 打开了数据库,再关闭
else
{
sqliteDatabase.close();
#ifdef QT_DEBUG
qDebug() << "数据库已经打开,现在已经关了";
#endif
}
// 4、移除数据库连接
QSqlDatabase::removeDatabase("QSQLITE");
////////////////////////////////////////////////////////////////////////////////////
下面的增删改 都是需要设置 QSqlTableModel 为 手动提交,代码如下
// 设置手动提交
pModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
8、添加
// 1、获取当前选择行
int curTabIndex = tabWidget->currentIndex();
// 1.1 若没有选择行
if (-1 == curTabIndex)
{
QMessageBox::information(this, tr("tip"), tr("err, threre is no tab"));
return;
}
// 2、获取当前选择行
int rowIndex = tableViewArr[curTabIndex]->currentIndex().row();
// 添加到哪一行
int addRowIndex = 0;
// 2.1 若没有选择行
if (-1 == rowIndex)
{
// 默认设置选择当前tableview的最后一行
addRowIndex = tableViewArr[curTabIndex]->model()->rowCount();
}
// 2.2 若已经选择行
else
{
// 添加到选择行的下一行
addRowIndex = rowIndex + 1;
}
// 3、向sqltableModel中添加一行
bool isAdd = sqlTableModel[curTabIndex]->insertRow(addRowIndex);
// 3.1 若添加失败
if (false == isAdd)
{
// 提示添加失败
QMessageBox::warning(this, tr("tip"), tr("add failed, add a new row failed"));
return;
}
9、删除
// 1、得到当前选择的是哪一个tab
int curTabIndex = tabWidget->currentIndex();
if (-1 == curTabIndex)
{
QMessageBox::warning(this, tr("warning"), tr("delete failed, because there is no tab"));
return;
}
// 2、得到选中的行
QItemSelectionModel *selections = tableViewArr[curTabIndex]->selectionModel();
QModelIndexList selected = selections->selectedIndexes();
// 保存选择了哪些行
QVector delRowsArr;
delRowsArr.clear();
foreach (QModelIndex index, selected)
{
int rowIndex = index.row();
#ifdef QT_DEBUG
qDebug() << "当前行为 = " << rowIndex + 1;
#endif
int size = delRowsArr.count();
bool isExist = false;
for (int i = 0; i < size; i++)
{
// 若删除行已经存在
if (delRowsArr[i] == rowIndex)
{
isExist = true;
break;
}
}
// 若已经存在,则不加入到删除数组中
if (true == isExist)
{
}
else
{
delRowsArr.append(rowIndex);
}
}
const int delArrCount = delRowsArr.count();
if (0 == delArrCount)
{
QMessageBox::warning(this, tr("warning"), tr("delete failed, because there is no selected row"));
return ;
}
// 3、确认是否删除
int isOk = QMessageBox::warning(this, tr("warning"), tr("Are u sure del the selected row"), QMessageBox::Yes, QMessageBox::No);
if (QMessageBox::No == isOk)
{
return;
}
#ifdef QT_DEBUG
qDebug() << "删除的行总数 = " << delArrCount;
#endif
for (int i; i < delArrCount; i++)
{
sqlTableModel[curTabIndex]->removeRow(delRowsArr[i]);
}
// 4、提交
bool isSuccess = sqlTableModel[curTabIndex]->submitAll();//tableViewArr[curTabIndex]->model()->submit();
if (false == isSuccess)
{
// 删除提交失败,则回滚
sqlTableModel[curTabIndex]->revertAll();
// 提示删除失败
QMessageBox::warning(this, tr("warning"), tr("delete falied , submit failed"));
return;
}
#ifdef QT_DEBUG
qDebug() << "delete success , submit success";
#endif
10、修改
QTableview,双击单元格, 可以修改数据, 若同时修改数据库,需要手动提交修改结果
。。
11、提交
// 1、获取当前选择的是哪一个tab
int curTabIndex = tabWidget->currentIndex();
// 若没有tab
if (-1 == curTabIndex)
{
QMessageBox::warning(this, tr("tip"), tr("err, there is no tab"));
return;
}
// 2、提交当前tab下的新增记录
int isSubmitSuccess = sqlTableModel[curTabIndex]->submitAll();
// 2.1 提交失败
if (false == isSubmitSuccess)
{
QMessageBox::warning(this, tr("submit"), tr("the behavior of submit has failed, Please Check new line's Id"));
return;
}
---------------------------------------------------------------------------------------
文章最前面的图片中,设置的有点击工具栏按钮实现 选择 QTableView的上一个和下一个, 还有最前 和最后
---------------------------------------------------------------------------------------
12、最前
// 1、获取当前选择的是哪一个tab
int curTabIndex = tabWidget->currentIndex();
// 若没有tab
if (-1 == curTabIndex)
{
QMessageBox::warning(this, tr("warning"), tr("err, there is no tab"));
return;
}
// 2、设置选中第一行
int tableViewCount = tableViewArr[curTabIndex]->model()->rowCount();
if (0 < tableViewCount)
{
tableViewArr[curTabIndex]->selectRow(0);
}
13、上一个
// 1、获取当前选择的是哪一个tab
int curTabIndex = tabWidget->currentIndex();
// 若没有tab
if (-1 == curTabIndex)
{
QMessageBox::warning(this, tr("warning"), tr("err, there is no tab"));
return;
}
// 2、获取当前行
int curRowIndex = tableViewArr[curTabIndex]->currentIndex().row();
#ifdef QT_DEBUG
qDebug() << "上一个 , 当前行索引 = " << curRowIndex;
#endif //QT_DEBUG
// 若没有选择,则默认选择第一个
if (-1 == curRowIndex)
{
curRowIndex = 0;
}
else
{
if (0 < curRowIndex)
{
curRowIndex -= 1;
}
}
tableViewArr[curTabIndex]->selectRow(curRowIndex);
14、下一个
// 1、获取当前选择的是哪一个tab
int curTabIndex = tabWidget->currentIndex();
// 若没有tab
if (-1 == curTabIndex)
{
QMessageBox::warning(this, tr("warning"), tr("err, there is no tab"));
return;
}
// 2、获取当前行
int curRowIndex = tableViewArr[curTabIndex]->currentIndex().row();
int totalCount = tableViewArr[curTabIndex]->model()->rowCount();
// 若没有选择行
if (-1 == curRowIndex)
{
curRowIndex = 0;
}
else
{
#ifdef QT_DEBUG
qDebug() << "下一个,当前行 = " << curRowIndex << " 总行数 = " << totalCount;
#endif
if (curRowIndex < totalCount - 1)
{
curRowIndex += 1;
}
}
#ifdef QT_DEBUG
qDebug() << "下一个, +1 后 = " << curRowIndex;
#endif
tableViewArr[curTabIndex]->selectRow(curRowIndex);
15、最后
// 1、获取当前选择的是哪一个tab
int curTabIndex = tabWidget->currentIndex();
// 若没有tab
if (-1 == curTabIndex)
{
QMessageBox::warning(this, tr("warning"), tr("err, there is no tab"));
return;
}
// 2、设置选中最后一行
int totalCount = tableViewArr[curTabIndex]->model()->rowCount();
tableViewArr[curTabIndex]->selectRow(totalCount - 1);
---------------------------------------------------------------------------------------
下面的代码是关于 查找 模块的
---------------------------------------------------------------------------------------
16、查找实现
这里, 支持 模糊查找
QString str = keyStr;
#ifdef QT_DEBUG
qDebug() << "输入框内容 = " << str;
#endif
// 1、获取当前选择的是哪一个tab
int curTabIndex = tabWidget->currentIndex();
// 若没有tab页
if (-1 == curTabIndex)
{
return;
}
// 2、取从哪一列开始查找
QString columnName = columnNameStr;
// 3、若输入框没有输入
// 输入框有内容,则应该按照选择来筛选
QString filterStr("");
filterStr = QString(tr("%1 like '%%2%%'")).arg(columnName).arg(str);
// 根据条件查找
sqlTableModel[curTabIndex]->setFilter(filterStr);
// 4、刷新显示界面数据
sqlTableModel[curTabIndex]->select();
模糊查找关键代码如下,使用的是QSqlTableModel的Filter函数
QString filterStr("");
filterStr = QString(tr("%1 like '%%2%%'")).arg(columnName).arg(str);
// 根据条件查找
sqlTableModel[curTabIndex]->setFilter(filterStr);
------------------------------------------------------------------------------
17、排序
这里支持升序和降序
当选择的排序方式发生变化后,执行下面的代码执行排序
// 0、哪一个tab被选中
int curTabIndex = tabWidget->currentIndex();
if (-1 == curTabIndex)
{
return;
}
QString curStr = text;
// 1、每一项都是 列名 + 空格 + 排序方式
QString columnName("");
QString sortType("");
int spacePos = curStr.indexOf(" ");
// 2、列名
columnName = curStr.mid(0, spacePos);
#ifdef QT_DEBUG
// qDebug() << "列名= " << columnName;
#endif
// 3、排序方式
sortType = curStr.mid(spacePos + 1, curStr.length());
#ifdef QT_DEBUG
// qDebug() << "排序方式= " << sortType;
#endif
// 4、按照选择的排序方式排序
// 4.1 按照哪一列排序
int sortIndex = 0;
for (int i = 0; i < curTableViewColumnNameList.count(); i++)
{
// 若相等
if (columnName == curTableViewColumnNameList.at(i))
{
break;
}
sortIndex += 1;
}
// 升序还是降序
// 0 - 升序, 1 降序
if ("ASC" == sortType)
{
// 5、排序
sqlTableModel[curTabIndex]->setSort(sortIndex, Qt::AscendingOrder);
}
else if ("DESC" == sortType)
{
// 5、排序
sqlTableModel[curTabIndex]->setSort(sortIndex, Qt::DescendingOrder);
}
// 查询现实
sqlTableModel[curTabIndex]->select();