QTableView开发入门
1. QTableView 基础介绍
QTableView 是 Qt 中用于显示表格数据的控件,属于模型/视图架构的一部分。它提供了灵活的方式来展示和编辑二维表格数据。
主要特点:
-
基于模型/视图架构
-
支持大型数据集
-
提供排序、筛选功能
-
可自定义单元格显示和编辑方式
-
支持表头自定义
2. 基本使用
2.1 简单示例
#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建数据模型
QStandardItemModel model(4, 3); // 4行3列
// 填充数据
for (int row = 0; row < 4; ++row) {
for (int col = 0; col < 3; ++col) {
QStandardItem *item = new QStandardItem(QString("行%1 列%2").arg(row+1).arg(col+1));
model.setItem(row, col, item);
}
}
// 设置表头
model.setHorizontalHeaderLabels({"列1", "列2", "列3"});
model.setVerticalHeaderLabels({"行1", "行2", "行3", "行4"});
// 创建并设置TableView
QTableView tableView;
tableView.setModel(&model);
tableView.setWindowTitle("简单表格示例");
tableView.resize(500, 300);
tableView.show();
return app.exec();
}
2.2 常用方法
// 设置选择模式
tableView.setSelectionMode(QAbstractItemView::SingleSelection); // 单选
tableView.setSelectionMode(QAbstractItemView::MultiSelection); // 多选
// 设置选择行为
tableView.setSelectionBehavior(QAbstractItemView::SelectRows); // 整行选择
tableView.setSelectionBehavior(QAbstractItemView::SelectItems); // 单个单元格选择
// 设置网格线
tableView.setShowGrid(true); // 显示网格线
tableView.setGridStyle(Qt::DotLine); // 点线网格
// 设置表头
tableView.horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 自动拉伸
tableView.verticalHeader()->setDefaultSectionSize(30); // 设置默认行高
// 排序功能
tableView.setSortingEnabled(true); // 启用排序
3. 数据模型使用
3.1 使用 QStandardItemModel
QStandardItemModel *model = new QStandardItemModel(5, 3, this);
// 填充数据
for (int row = 0; row < 5; ++row) {
for (int col = 0; col < 3; ++col) {
QStandardItem *item = new QStandardItem(QString("数据 %1-%2").arg(row).arg(col));
// 设置文本颜色
if (col == 1) {
item->setForeground(QBrush(Qt::blue));
}
// 设置背景色
if (row % 2 == 0) {
item->setBackground(QBrush(QColor(240, 240, 240)));
}
// 设置文本对齐
item->setTextAlignment(Qt::AlignCenter);
model->setItem(row, col, item);
}
}
// 设置表头
model->setHorizontalHeaderLabels({"姓名", "年龄", "职业"});
ui->tableView->setModel(model);
3.2 使用自定义模型
继承 QAbstractTableModel 创建自定义表格模型:
class CustomTableModel : public QAbstractTableModel {
Q_OBJECT
public:
explicit CustomTableModel(QObject *parent = nullptr);
// 必须重写的方法
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
// 可选重写的方法
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
// 自定义方法
void addData(const QList<QStringList> &newData);
private:
QList<QStringList> m_data;
};
// 实现示例
int CustomTableModel::rowCount(const QModelIndex &parent) const {
return parent.isValid() ? 0 : m_data.size();
}
int CustomTableModel::columnCount(const QModelIndex &parent) const {
return parent.isValid() ? 0 : (m_data.isEmpty() ? 0 : m_data.first().size());
}
QVariant CustomTableModel::data(const QModelIndex &index, int role) const {
if (!index.isValid() ||
index.row() >= m_data.size() ||
index.column() >= m_data.first().size())
return QVariant();
switch (role) {
case Qt::DisplayRole:
case Qt::EditRole:
return m_data[index.row()][index.column()];
case Qt::TextAlignmentRole:
return Qt::AlignCenter;
case Qt::BackgroundRole:
return index.row() % 2 == 0 ? QColor(240, 240, 240) : QColor(255, 255, 255);
default:
return QVariant();
}
}
4. 表格定制化
4.1 使用委托自定义单元格
class CustomDelegate : public QStyledItemDelegate {
public:
using QStyledItemDelegate::QStyledItemDelegate;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
if (index.column() == 1) { // 特殊处理第二列
painter->save();
// 绘制背景
if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, option.palette.highlight());
} else {
painter->fillRect(option.rect, QColor("#f8f8f8"));
}
// 绘制文本
painter->setPen(option.state & QStyle::State_Selected ?
option.palette.highlightedText().color() : Qt::darkBlue);
painter->drawText(option.rect.adjusted(5, 0, -5, 0),
Qt::AlignVCenter | Qt::AlignRight,
index.data().toString());
painter->restore();
} else {
QStyledItemDelegate::paint(painter, option, index);
}
}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override {
QSize size = QStyledItemDelegate::sizeHint(option, index);
size.setHeight(35); // 固定行高
return size;
}
};
// 使用委托
ui->tableView->setItemDelegate(new CustomDelegate(this));
4.2 表头定制
// 设置表头样式
QHeaderView *header = ui->tableView->horizontalHeader();
header->setDefaultAlignment(Qt::AlignCenter);
header->setSectionResizeMode(QHeaderView::Interactive);
header->setStretchLastSection(true);
header->setSectionsClickable(true);
// 自定义表头
class CustomHeader : public QHeaderView {
// 实现自定义绘制等
};
// 设置自定义表头
ui->tableView->setHorizontalHeader(new CustomHeader(Qt::Horizontal, ui->tableView));
5. 交互功能实现
5.1 选择操作
// 获取选中单元格
QModelIndexList selected = ui->tableView->selectionModel()->selectedIndexes();
// 获取选中行
QModelIndexList selectedRows;
foreach (const QModelIndex &index, ui->tableView->selectionModel()->selectedIndexes()) {
if (!selectedRows.contains(index.row()))
selectedRows << index.row();
}
// 获取选中数据
foreach (const QModelIndex &index, selected) {
qDebug() << "选中的数据:" << index.data().toString()
<< "行:" << index.row() << "列:" << index.column();
}
5.2 排序和筛选
// 使用代理模型实现排序和筛选
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(sourceModel);
ui->tableView->setModel(proxyModel);
// 设置筛选
proxyModel->setFilterKeyColumn(0); // 根据第一列筛选
proxyModel->setFilterRegExp(QRegExp("搜索文本", Qt::CaseInsensitive));
// 动态排序
connect(ui->tableView->horizontalHeader(), &QHeaderView::sectionClicked,
[proxyModel](int logicalIndex) {
proxyModel->sort(logicalIndex);
});
6. 高级功能
6.1 合并单元格
// 需要继承QTableView并重写paintEvent
void CustomTableView::paintEvent(QPaintEvent *event) {
QTableView::paintEvent(event);
QPainter painter(viewport());
painter.setPen(Qt::red);
// 合并第1行第1列到第3行第2列
QRect rect1 = visualRect(model()->index(1, 1));
QRect rect2 = visualRect(model()->index(3, 2));
QRect mergedRect = rect1.united(rect2);
painter.drawRect(mergedRect.adjusted(0, 0, -1, -1));
painter.drawText(mergedRect, Qt::AlignCenter, "合并区域");
}
6.2 拖放功能
// 启用拖放
ui->tableView->setDragEnabled(true);
ui->tableView->setAcceptDrops(true);
ui->tableView->setDropIndicatorShown(true);
ui->tableView->setDragDropMode(QAbstractItemView::InternalMove);
// 在模型中实现拖放相关方法
Qt::DropActions CustomModel::supportedDropActions() const {
return Qt::CopyAction | Qt::MoveAction;
}
// 实现mimeData()和dropMimeData()方法
7. 性能优化
-
大数据集处理:
// 使用fetchMore/canFetchMore实现懒加载 // 设置 uniformRowHeights 提高性能 ui->tableView->setUniformRowHeights(true);
-
减少不必要的刷新:
-
优化委托:避免在委托中进行复杂计算
-
使用模型测试:
new QAbstractItemModelTester(model, QAbstractItemModelTester::FailureReportingMode::Warning, this);