效果图
概述
- 本案例用于对数据库中的数据进行显示等其他操作。数据库的映射,插入等功能看此博客
- 框架:数据模型使用
QSqlTableModel
,视图使用QTableView
,表格的一些字体或者控件之类的使用QStyledItemDelegate
实现。
导航栏的变化实时的传回给表格,所有的数据库表都实现继承一个表格类,根据表格本身的特性可以设置自己的委托。数据库使用一个单列类进行管理,包括数据库的读取 ,创建,数据插入,以及对模型的映射等。
功能点
- 自选每页显示行数
- 跳转指定页面
- 上下翻页,最后/最前一页跳转
- 表格导出
- 表格查询
代码分析
导航栏
表格更新视图
- 每次使用过滤时要格外注意语句的条件
void QTablePages::updateTableView()
{
if (!m_dataModel)
return;
if (m_filter != QString())
{
int offset = (m_currentPage - 1) * m_pageLines;
QRegExp limitRegex("LIMIT\\s*(\\d+)");
QRegExp offsetRegex("OFFSET\\s*(\\d+)");
m_filter.replace(limitRegex, QString("LIMIT %1").arg(m_pageLines));
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;
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";
}
}
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);
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();
}
总结
- 知识理应共享,源码在此
- 导航栏,表格这些功能基本上都是单独封装好的,可以直接拿来用的