QTableWidget从继承QTableView,实质属于模型-视图范畴之内,只是带了默认模型(model)基于项目(item)的表格视图控件。我们不需要实现model内的数据加工。QTableWidget为应用程序提供了标准的表显示工具。QTableWidget中的项目(item)是由QTableWidgetItem来实现。QTableWidget各种属性可利用Qt自带的UI设计师来设置,如下图:
接下来我们定制 2行4列的表格视图。主要的代码 setRowCount,setColumnCount,setHorizontalHeaderLabels,setItem完成一个数据的填充。
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);//设置表格不能编辑
ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
ui->tableWidget->verticalHeader()->setVisible(false); //去除左右的列序号
ui->tableWidget->setStyleSheet("QHeaderView::section { border:none; height:30px;color:#555555;background:#F2F5F8;}QTableView::item:selected{background:#87CEFA;}");
ui->tableWidget->horizontalHeader()->setVisible(true); //去除表头
ui->tableWidget->setShowGrid(true); //设置显示格子线
ui->tableWidget->setColumnCount(4);//设置4列
ui->tableWidget->setColumnWidth(0, 111);
ui->tableWidget->setColumnWidth(1, 111);
ui->tableWidget->setColumnWidth(2, 111);
ui->tableWidget->setColumnWidth(3, 111);
ui->tableWidget->setRowCount(2);//设置2行
ui->tableWidget->horizontalHeader()->setFixedHeight(30); //表头高度
ui->tableWidget->verticalHeader()->setDefaultSectionSize(28); //设置表格行高
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
QStringList headerText;
headerText<< tr("类型1")<< tr("类型2") << tr("类型3") << tr("类型4"); //表头标题用QStringList来表示
ui->tableWidget->setHorizontalHeaderLabels(headerText);
ui->tableWidget->setColumnCount(headerText.count());//列数设置为与 headerText的行数相等
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);//固定表头
ui->tableWidget->horizontalHeader()->setSectionsClickable(false);
for (int row = 0; row < ui->tableWidget.rowCount(); ++row)
{
for (int col = 0; col < ui->tableWidget->columnCount(); ++col)
{
switch (col)
{
case 0:
item = new QTableWidgetItem("语文");
break;
case 1:
item = new QTableWidgetItem("数学");
break;
case 2:
item = new QTableWidgetItem("英语");
item->setTextColor(QColor(57, 125, 238));
break;
case 3:
item = new QTableWidgetItem("物理");
item->setTextColor(QColor(57, 125, 238));
break;
}
item->setTextAlignment(Qt::AlignCenter);//文本对齐格式
ui->tableWidget->setItem(row,col,item);//为单元格设置Item
}
row++;
}
操作起来很简单,但是在实际的业务场景中,我们更希望的是能从每一项获得业务数据模型,使用 QTableWidgetItem中的setData()方法。假设自定义业务模型类:class iteminfo
iteminfo k;
QVariant vart;
vart.setValue(k);
QTableWidgetItem *item = new QTableWidgetItem();
item->setData(Qt::UserRole,vart);
获取数据
item->data(Qt::UserRole).value<iteminfo>();
这边涉及到了两点,第一,业务数据模型,是人为自定义,所以需要向Qt 元对象系统(Meta-Object)申明该类型,Q_DECLARE_METATYPE(iteminfo),添加Q_DECLARE_METATYPE()宏将使所有基于模板的函数(包括QVariant)都知道该类型。注意,如果打算在队列信号和槽连接或QObject的属性系统中使用该类型,还必须在构造函数中调用qRegisterMetaType("iteminfo")函数,因为名称是在运行时解析的。
UI样式优化
在开发过程中 在用户体验上有些瑕疵,就是当选中某一行时,选中项出现虚线框并且某些项字体带有颜色的全消失了都恢复了默认颜色(黑色)。使用qss修改样式由于数据本身的颜色可以发生变化。所以不适合使用。这里使用QStyledItemDelegate(代理)的方式
#ifndef ITEMDELEGATE_H
#define ITEMDELEGATE_H
#include <QStyledItemDelegate>
class ItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
ItemDelegate(QObject *parent = nullptr);
virtual void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
};
#endif // ITEMDELEGATE_H
#include "itemdelegate.h"
#include "style/theme.h"
#include <QPainter>
ItemDelegate::ItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
}
void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem viewOption(option);
if (viewOption.state & QStyle::State_Selected)
{
painter->fillRect(viewOption.rect, QBrush(UI_SELECTTIEM_COLOR));
viewOption.state = viewOption.state & 0;//去掉选中时的虚线框
}
else
{
if (index.row() % 2 == 0)
{
painter->fillRect(viewOption.rect, QBrush(UI_EVENROW_COLOR));
}
else
{
painter->fillRect(viewOption.rect, QBrush(UI_ODDROW_COLOR));
}
if (viewOption.state & QStyle::State_HasFocus) {//去掉虚线框
viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
}
}
paintItemData(painter, viewOption, index.data(Qt::UserRole));
//如何做得通用 每个view 都有基础样式比如:交替变化色,悬浮色,选中色等
//再构造一个虚函数 子类化该基础样式
//高亮显示与普通显示时的前景色一致(即选中行和为选中时候的文字颜色一样)
viewOption.palette.setColor(QPalette::HighlightedText, index.data(Qt::ForegroundRole).value<QColor>());
//viewOption.palette.setColor(QPalette::Foreground, UI_SELECTTIEM_COLOR);
QStyledItemDelegate::paint(painter, viewOption, index);
}
结果如下图所示: