QT 使用QTableView读取数据库数据,表格分页,跳转,导出,过滤功能
·
效果图

概述
- 本案例用于对数据库中的数据进行显示等其他操作。数据库的映射,插入等功能看此博客
- 框架:数据模型使用
QSqlTableModel,视图使用QTableView,表格的一些字体或者控件之类的使用QStyledItemDelegate实现。
导航栏的变化实时的传回给表格,所有的数据库表都实现继承一个表格类,根据表格本身的特性可以设置自己的委托。数据库使用一个单列类进行管理,包括数据库的读取 ,创建,数据插入,以及对模型的映射等。
功能点
- 自选每页显示行数
- 跳转指定页面
- 上下翻页,最后/最前一页跳转
- 表格导出
- 表格查询
代码分析
导航栏
- 该部分不复杂主要和tableView进行联动
void PageNavigator::SetCurrentPage(int page) { if (m_curPage == page) { return; } if (page < 1) { page = 1; } if (page > (int)m_maxPage) { page = m_maxPage; } m_curPage = page; ui->labelCurPage->setText(QString("第%1页/共%2页").arg(m_curPage).arg(m_maxPage)); UpdateButtonState(); emit SigCurrentPageChanged(m_curPage); // 通知 table 刷新 }
表格更新视图
- 每次使用过滤时要格外注意语句的条件
void QTablePages::updateTableView() { if (!m_dataModel) return; if (m_filter != QString()) // 有过滤条件的情况 { int offset = (m_currentPage - 1) * m_pageLines; // 使用正则表达式来匹配LIMIT和OFFSET后面的数字 QRegExp limitRegex("LIMIT\\s*(\\d+)"); QRegExp offsetRegex("OFFSET\\s*(\\d+)"); // 替换LIMIT m_filter.replace(limitRegex, QString("LIMIT %1").arg(m_pageLines)); // 替换OFFSET m_filter.replace(offsetRegex, QString("OFFSET %1").arg(offset)); m_dataModel->setFilter(m_filter); m_dataModel->select(); return; } int offset = (m_currentPage - 1) * m_pageLines; // 计算偏移量 要减1,因为从0开始 m_dataModel->setFilter(QString("1=1 ORDER BY time DESC LIMIT %1 OFFSET %2").arg(m_pageLines).arg(offset)); m_dataModel->select(); }
表格导出
- 简单的导出为csv格式,要是为excel格式,则需要引入excel的库
void QTablePages::exportToCSV()
{
if (!m_dataModel)
return;
QFileDialog dialog(this);
dialog.setOptions(QFileDialog::DontUseNativeDialog);
dialog.setWindowTitle(tr("表格导出"));
dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setNameFilter(tr("CSV Files (*.csv)"));
dialog.setStyleSheet("color: white;");
QString saveFileName;
if (dialog.exec())
{
saveFileName = dialog.selectedFiles().first();
QFileInfo fileInfo(saveFileName);
if (fileInfo.suffix().toLower() != "csv")
{
saveFileName += ".csv"; // 如果用户没有输入.csv,则添加它
}
}
// 如果用户取消了操作,则返回
if (saveFileName.isEmpty())
return;
// 打开一个文件用于写入
QFile file(saveFileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
// 处理错误
return;
}
/// 重置过滤条件-查询所有数据
int offset = getOffest();
int totalPages = getTotalPages();
QString filter = getFilter();
m_dataModel->setFilter(QString("1=1"));
m_dataModel->select();
QTextStream out(&file);
int columnCount = m_dataModel->columnCount() - 1;
// 写入列标题 操作列不写入
for (int i = 1; i < columnCount; i++)
{
out << m_dataModel->headerData(i, Qt::Horizontal).toString();
if (i < columnCount - 1)
out << ",";
}
out << "\n";
// 写入数据
auto formatDateTime = [](const QDateTime &dateTime)
{
return dateTime.toString("yyyy-MM-dd HH:mm:ss");
};
for (int i = 0; i < m_dataModel->rowCount(); i++)
{
QSqlRecord record = m_dataModel->record(i);
for (int j = 1; j < columnCount; j++)
{
QSqlField field = record.field(j);
if (field.type() == QVariant::DateTime)
{
// 如果字段是日期时间类型,则格式化输出
QDateTime dateTime = field.value().toDateTime();
out << formatDateTime(dateTime);
}
else
{
// 其他字段按原样输出
out << field.value().toString();
}
if (j < columnCount - 1)
out << ",";
}
out << "\n";
}
// 关闭文件
file.close();
// 恢复过滤条件
if (filter != QString())
{
m_dataModel->setFilter(filter);
}
else
{
m_dataModel->setFilter(QString("1=1 ORDER BY time DESC LIMIT %1 OFFSET %2").arg(totalPages).arg(offset));
}
m_dataModel->select();
}
表格过滤
- 数据过滤的条件,要和导航栏的偏移分开获取,不然过滤会出现问题
void QTablePages::refreshData(const QString &dateFrom, const QString &dateTo, const QString &content)
{
if (m_dataModel == nullptr)
return;
QString filter;
// 获取日期范围
QString dateFilter = "time BETWEEN '" + dateFrom + "' AND '" + dateTo + "'";
// 获取内容过滤条件
QString contentFilter;
if (!content.isEmpty())
{
contentFilter = "content LIKE '%" + content + "%'";
}
// 构建最终的过滤条件
if (!filter.isEmpty())
{
if (!dateFilter.isEmpty())
{
filter += " AND " + dateFilter;
}
if (!contentFilter.isEmpty())
{
filter += " AND " + contentFilter;
}
}
else
{
if (!dateFilter.isEmpty())
{
filter = dateFilter;
if (!contentFilter.isEmpty())
{
filter += " AND " + contentFilter;
}
}
else if (!contentFilter.isEmpty())
{
filter = contentFilter;
}
}
// 重置导航条数据
m_dataModel->setFilter(filter);
m_dataModel->select();
m_pageNavBar->updateNavbar(m_dataModel->rowCount(), m_pageLines);
// 计算偏移量,要减1,因为从0开始
int offset = (m_currentPage - 1) * m_pageLines;
// 添加排序、限制和偏移量到过滤条件
if (!filter.isEmpty())
{
filter += " ORDER BY time DESC LIMIT " + QString::number(m_pageLines) + " OFFSET " + QString::number(offset);
}
else
{
filter = "1=1 ORDER BY time DESC LIMIT " + QString::number(m_pageLines) + " OFFSET " + QString::number(offset);
}
m_filter = filter;
// 应用最终的过滤条件
m_dataModel->setFilter(filter);
m_dataModel->select();
}
总结
- 知识理应共享,源码在此
- 导航栏,表格这些功能基本上都是单独封装好的,可以直接拿来用的
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)