TOP

Qt实现表格树控件-支持多级表头(一)
2019-08-14 00:08:59 】 浏览:193
Tags:实现 表格 控件 支持 多级 表头

原文链接:Qt实现表格树控件-支持多级表头

一、概述

之前写过一篇关于表格控件多级表头的文章,喜欢的话可以参考Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等。今天这篇文章带来了比表格更加复杂的控件-树控件多级表头实现。

在Qt中,表格控件包含有水平和垂直表头,但是常规使用模式下都是只能实现一级表头,而树控件虽然包含有了branch分支,这也间接的削弱了他自身的表头功能,细心的同学可能会发现Qt自带的QTreeView树控件只包含有水平表头,没有了垂直表头。

既然Qt自带的控件中没有这个功能,那么我们只能自己去实现了。

要实现多级表头功能方式也多种多样,之前就看到过几篇关于实现多级表头的文章,总体可以分为如下两种方式

  1. 表头使用一个表格来模拟
  2. 通过给表头自定义Model

今天这篇文章我们是通过方式2来实现多级表头。如效果图所示,实现的是一个树控件的多级表头,并且他还包含了垂直列头,实现这个控件所需要完成的代码量还是比较多的。本篇文章可以算作是一个开头吧,后续会逐步把关键功能的实现方式分享出来。

二、效果展示

三、实现方式

本篇文章中的控件看起来是一个树控件,但是他又具备了表格控件该有的一些特性,比如垂直表头、多级水平表头等等。要实现这样的树控件,我们有两个大的方向可以去考虑

  1. 重写表格控件,实现branch
  2. 表格控件+树控件

方式1重写表格控件实行branch的工作量是比较大的,而且需要把Qt原本的代码迁出来,工作量会比加大,个人选择了发你。

方式2是表格控件+树控件的实现方式,说白了就是表格控件提供水平和垂直表头,树控件提供内容展示,听起来好像没毛病,那么还等什么,直接干呗。

既然大方向定了,那么接下来可能就是一些细节问题的确定。

  1. 多级水平表头
  2. 垂直列头拖拽时,实现树控件行高同步变动
  3. 自绘branch

以上三个问题都是实现表格树控件时遇到的一些比较棘手的问题,后续会分别通过单独的文章来进行讲解,今天这篇文章也是我们的第一讲,怎么实现水平多级表头

四、多级表头

第一节我们也说了,实现多级表头我们使用重写model的方式来实现,接下来就是贴代码的时候。

1、数据源

经常重写model的同学对如下代码应该不陌生,对于继承自QAbstractItemModel的数据源肯定是需要重写该类的所有纯虚方法,包括所有间接父类的纯虚方法。

除此之外自定义model应该还需要提供一个可以合并单元格的方法,为什么呢?因为我们多级表头需要。比如说我们一级表头下有3个二级表头,那这就说明一级表头合并了3列,使得本身的3列数据变成一列。

class HHeaderModel : public QAbstractItemModel
{
    struct ModelData //模型数据结构
    {
        QString text;

        ModelData() : text("")
        {
        }
    };

    Q_OBJECT

public:
    HHeaderModel(QObject * parent = 0);
    ~HHeaderModel();

public:
    void setItem(int row, int col, const QString & text);

    QString item(int row, int col);

    void setSpan(int firstRow, int firstColumn, int rowSpanCount, int columnSpanCount);
    const CellSpan& getSpan(int row, int column);

public:
    virtual QModelIndex index(int row, int column, const QModelIndex & parent) const override;
    virtual QModelIndex parent(const QModelIndex & child) const override;
    virtual int rowCount(const QModelIndex & parent) const override;
    virtual int columnCount(const QModelIndex & parent) const override;
    virtual QVariant data(const QModelIndex & index, int role) const override;
    virtual Qt::ItemFlags flags(const QModelIndex & index) const override;
    virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) override;
    virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;

private:
    //找到对应的模型数据
    ModelData * modelData(const QModelIndex & index) const;

private:
    //key rowNo,  key colNo
    QMap<int, QMap<int, ModelData *> > m_modelDataMap;
    int m_iMaxCol;

    CellSpan m_InvalidCellSpan;
    QList<CellSpan> m_cellSpanList;
};

以上便是model的头文件声明,其中重写父类的虚方法这里就不做过多说明,和平时重写其他数据源没有区别,这里多了重点说明下setSpan接口。

void HHeaderModel::setSpan(int firstRow, int firstColumn, int rowSpanCount, int columnSpanCount)
{
    for (int row = firstRow; row < firstRow + rowSpanCount; ++row)
    {
        for (int col = firstColumn; col < firstColumn + columnSpanCount; ++col)
        {
            m_cellSpanList.append(CellSpan(row, col, rowSpanCount, columnSpanCount, firstRow, firstColumn));
        }
    }
}

const CellSpan& HHeaderModel::getSpan(int row, int column)
{
    for (QList<CellSpan>::const_iterator iter = m_cellSpanList.begin(); iter != m_cellSpanList.end(); ++iter)
    {
        if  
		
Qt实现表格树控件-支持多级表头(一) https://www.cppentry.com/bencandy.php?fid=49&id=228548

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇编程题常见输入格式处理方法 下一篇C++中const关键字用法总结