先上效果:

可以看到表头实现了绘制两行,绘制多行其实原理都一样,知道两行表头的写法就可以扩展显示更多行,主要原理是重写paintSection函数。
思路流程如下:
- 自定义MultiRowHeader类继承QHeaderView,重写paintSection函数实现双行表头绘制
- 使用QStringList存储主标题和子标题数据
- 通过QPair记录合并列的开始和结束位置
- 在paintSection中划分上下两部分区域分别绘制主标题和子标题
- 示例代码展示了如何加载QTableWidget并设置多行表头参数
重写表头代码:
//自定义表头,实现多行表头(显示两行)
class MultiRowHeader : public QHeaderView
{
Q_OBJECT
public:
MultiRowHeader(Qt::Orientation orientation, QWidget* parent = nullptr);
void setMainHead(QStringList lst);//设置主标题
void setSubHead(QStringList lst);//设置子标题
void setColInfo(QPair<int, int> tmp);//设置子标题开始和结束行的位置
void reset();//重置参数
void setHeaderData(QStringList lst);//设置表头信息
QString getHeaderData(int section);//获取HeaderData值
protected:
void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const override;
private:
QStringList m_lstDataHead;//主标题
QStringList m_lstSubDatahead;//子标题
QPair<int, int> m_colStart2End;//记录开始和结束列
QStringList m_lstHeaderData;//存储HeaderData,方便拿取
};
MultiRowHeader::MultiRowHeader(Qt::Orientation orientation, QWidget * parent) : QHeaderView(orientation, parent)
{
setMinimumHeight(80);
setMinimumWidth(100);
}
void MultiRowHeader::setMainHead(QStringList lst)
{
m_lstDataHead = lst;
}
void MultiRowHeader::setSubHead(QStringList lst)
{
m_lstSubDatahead = lst;
}
void MultiRowHeader::setColInfo(QPair<int, int> tmp)
{
m_colStart2End = tmp;
}
void MultiRowHeader::reset()
{
m_lstDataHead.clear();
m_lstSubDatahead.clear();
m_colStart2End = QPair<int, int>(0, 0);
}
void MultiRowHeader::setHeaderData(QStringList lst)
{
m_lstHeaderData = lst;
}
QString MultiRowHeader::getHeaderData(int section)
{
if (m_lstHeaderData.size() < section || section < 0)
{
return "";
}
return m_lstHeaderData.at(section);
}
class MultiRowHeader : public QHeaderView {
Q_OBJECT
public:
MultiRowHeader(Qt::Orientation orientation, QWidget* parent = nullptr)
: QHeaderView(orientation, parent) {}
QStringList dataHead;//主标题
QStringList sub_datahead;//子标题
QPair<int,int> colStart2End;//记录开始和结束列
protected:
void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const override {
painter->setPen(Qt::black);
if (logicalIndex >= colStart2End.first && logicalIndex < colStart2End.second)
{
QRect topRect = rect;
topRect.setHeight(rect.height() / 2);
topRect.setWidth(rect.width() * (colStart2End.second - colStart2End.first));//跨多列文字居中
//填充标题颜色
// painter->fillRect(topRect, Qt::gray);
if ( logicalIndex == colStart2End.first)
{
QString str=dataHead.at(colStart2End.first);
painter->drawText(topRect, Qt::AlignCenter, str);
}
QRect bottomRect = rect;
bottomRect.setTop(topRect.bottom());
// painter->fillRect(bottomRect, Qt::lightGray);
int nIndex=logicalIndex-colStart2End.first;
QString str=sub_datahead.at(nIndex);
painter->drawText(bottomRect, Qt::AlignCenter, str);
// 绘制上部分和下部分之间的水平分隔线
painter->drawLine(topRect.left(), topRect.top(), topRect.right(), topRect.top());
painter->drawRect(bottomRect);
}
else {
// painter->fillRect(rect, Qt::lightGray);
int nIndex=logicalIndex;
if(logicalIndex>=colStart2End.second)
{
nIndex=nIndex-sub_datahead.size()+1;
}
QString str=dataHead.at(nIndex);
painter->drawText(rect, Qt::AlignCenter, str);
//绘制边框线
painter->drawRect(rect);
}
}
};
加载QTableWidget的代码:
void MainWindow::loadTable()
{
QStringList main_dataHead;
main_dataHead<<u8"序号"<<u8"A"<<u8"B"
<<u8"C"<<u8"D"<<u8"E";
QStringList sub_dataHead;
sub_dataHead<<u8"a1"<<u8"a2"<<u8"a3";
QTableWidget *table = new QTableWidget(1, main_dataHead.size()+sub_dataHead.size()-1);
MultiRowHeader *customHeader=new MultiRowHeader(Qt::Horizontal, table);
table->setHorizontalHeader(customHeader);
customHeader->dataHead=main_dataHead;
customHeader->sub_datahead=sub_dataHead;
// 计算多行表头的开始和起始col
int start=0;
int end=0;
for(int i=0;i<main_dataHead.size();i++)
{
if(main_dataHead.at(i)==u8"A")
{
start=i;
end=i+sub_dataHead.size();
break;
}
}
customHeader->colStart2End=QPair<int,int>(start,end);
table->horizontalHeader()->setDefaultSectionSize(150);
table->horizontalHeader()->setMinimumHeight(100);
// 合并表头单元格
// table->setSpan(0, 1, 1, 3); // 将第一行的第二列到第四列合并
setCentralWidget(table);
}
875

被折叠的 条评论
为什么被折叠?



