QTableWidget实现多行表头

先上效果:

可以看到表头实现了绘制两行,绘制多行其实原理都一样,知道两行表头的写法就可以扩展显示更多行,主要原理是重写paintSection函数。

思路流程如下:

  1. 自定义MultiRowHeader类继承QHeaderView,重写paintSection函数实现双行表头绘制
  2. 使用QStringList存储主标题和子标题数据
  3. 通过QPair记录合并列的开始和结束位置
  4. 在paintSection中划分上下两部分区域分别绘制主标题和子标题
  5. 示例代码展示了如何加载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);
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值