QT的TableView实现多级表头
最近项目需要支持多级表头,QT本身不支持。可重写QHeaderView表头实现。
demo如下:
FSItemDelegate.h
#pragma once
/*
自定义委托类
*/
#include <QItemDelegate>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QComboBox>
#include <QStandardItemModel>
#include <QLineEdit>
#include <QDebug>
#define FS_WHITE_BRUSH QBrush((QColor(255, 255, 255)))
#define FS_RED_BRUSH QBrush((QColor(255, 0, 0)))
#define FS_GREEN_BRUSH QBrush((QColor(0, 255, 0)))
enum class DELEGATE_TYPE
{
READONLY, //只读委托
EDIDTEXT, //可修改文本框委托
COMBOBOX, //组合框
PASSWDLINE, //密码修改框
};
// 只读委托
class ReadOnlyDelegate : public QItemDelegate
{
Q_OBJECT
public:
ReadOnlyDelegate(QObject *parent = 0) : QItemDelegate(parent) {
}
QWidget *createEditor(QWidget*parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
return nullptr;
}
};
MultistageHeader.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_MultistageHeader.h"
#include "RbTableHeaderView.h"
#include "FSItemDelegate.h"
#include <QTableView>
#include <QHBoxLayout>
#include <QStandardItemModel>
#include "string"
#include <QString>
class MultistageHeader : public QWidget
{
Q_OBJECT
public:
MultistageHeader(QWidget *parent = Q_NULLPTR);
private:
Ui::MultistageHeaderClass ui;
RbTableHeaderView* m_pHeader;
QStandardItemModel* m_pDataModel;
QList<QStandardItem*> m_pVecItems;
QTableView * m_pView;
QHBoxLayout* m_pLayout = nullptr;
QHBoxLayout* m_Hlayout;
};
RbTableHeaderView.h
#ifndef RBTABLEHEADERVIEW_H_
#define RBTABLEHEADERVIEW_H_
#include <QHeaderView>
#include <QAbstractTableModel>
#include <QModelIndex>
#include <QHash>
#include <QPair>
enum eRbHeaderRole
{
COLUMN_SPAN_ROLE = Qt::UserRole + 1,
ROW_SPAN_ROLE,
COLUMN_SIZE_ROLE,
ROW_SIZE_ROLE,
};
class RbTableHeaderItem
{
public:
RbTableHeaderItem(RbTableHeaderItem* parent = nullptr);
RbTableHeaderItem(int arow, int acolumn, RbTableHeaderItem* parent = 0);
virtual ~RbTableHeaderItem();
// interface
RbTableHeaderItem* insertChild(int row, int col);
const RbTableHeaderItem* child(int row, int col) const;
RbTableHeaderItem* child(int row, int col);
void setData(const QVariant& data, int role);
QVariant data(int role = Qt::UserRole + 1) const;
inline int column() const {
return column_prop; }
inline int row() const {
return row_prop; }
RbTableHeaderItem* parent() {
return parent_item; }
void setText(const QString& text);
void clear();
private:
// properties
int row_prop; //当前表格在表头中所在行
int column_prop; //当前表格在表头中所在行
// inherent features
RbTableHeaderItem* parent_item;
QHash<QPair<int, int>, RbTableHeaderItem*> child_items;
QHash<int, QVariant> role_datas; //
};
class RbTableHeaderModel : public QAbstractTableModel
{
Q_OBJECT
public:
RbTableHeaderModel(int rows, int cols, QObject* parent = 0);
virtual ~RbTableHeaderModel();
public:
// override
virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const Q_DECL_OVERRIDE;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE {
Q_UNUSED(parent); return row_count_prop; }
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE {
Q_UNUSED(parent); return column_count_prop; }
virtual QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) Q_DECL_OVERRIDE;
virtual Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
private:
// properties
int row_count_prop; //表头行总数
int column_count_prop; //表头列总数
// inherent features
RbTableHeaderItem* root_item; //表头视图模型的根节点
};
class RbTableHeaderView : public QHeaderView
{
Q_OBJECT
public:
RbTableHeaderView(Qt::Orientation orientation, int rows, int columns, QWidget* parent = 0);
virtual ~RbTableHeaderView();
void setRowHeight(int row, int rowHeight);
void setColumnWidth(int col, int colWidth);
void setSpan(int row, int column, int rowSpanCount, int columnSpanCount);
void setCellBackgroundColor(const QModelIndex& index, const QColor&);
void setCellForegroundColor(const QModelIndex& index, const QColor&);
protected:
// override
virtual void mousePressEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
virtual QModelIndex indexAt(const QPoint&);
virtual void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const Q_DECL_OVERRIDE;
virtual QSize sectionSizeFromContents(int logicalIndex) const Q_DECL_OVERRIDE;
// inherent features
QModelIndex columnSpanIndex(const QModelIndex& currentIndex) const;
QModelIndex rowSpanIndex(const QModelIndex& currentIndex) const;
int columnSpanSize(int row, int from, int spanCount) const;
int rowSpanSize(int column, int from, int spanCount) const;
int getSectionRange(QModelIndex& index, int* beginSection, int* endSection) const;
protected slots:
void onSectionResized(int logicalIdx, int oldSize, int newSize);
signals:
void sectionPressed(int from, int to);
};
#endif /* RBTABLEHEADERVIEW_H_ */
MultistageHeader.cpp
#include "MultistageHeader.h"
MultistageHeader::MultistageHeader(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
m_pView = new QTableView(this);
m_pView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_pView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(tableContextMenuRequested(QPoint)));
m_pHeader = new RbTableHeaderView(Qt::Horizontal, 3, 8, m_pView);
QAbstractItemModel* pHeaderModel = m_pHeader->model();
m_pHeader->setSpan(0, 0, 1, 4);
m_pHeader->setSpan(0, 4, 1, 4);
m_pHeader->setSpan(1, 0, 1, 2);
m_pHeader->setSpan(1, 2, 1, 2);
m_pHeader->setSpan(1, 4, 1, 2);
m_pHeader->setSpan(1, 6, 1, 2);
for (int i = 0; i < 8; i++)
{
m_pHeader->setSpan(2, i, 1, 1);
}
//一级
pHeaderModel->setData(pHeaderModel->index(0, 0), QString(u8"横向尺寸"), Qt::DisplayRole);
pHeaderModel->setData(pHeaderModel->index(0, 4), QString(u8"纵向尺寸"), Qt::DisplayRole);
//二级
pHeaderModel->setData(pHeaderModel->index(1, 0), QStringLiteral("极耳宽度"), Qt::DisplayRole);
pHeaderModel->setData(pHeaderModel->index(1, 2), QStringLiteral("极耳高度"), Qt::DisplayRole);
pHeaderModel->setData(pHeaderModel->index(1, 4), QStringLiteral("极片宽度"), Qt::DisplayRole);
pHeaderModel->setData(pHeaderModel->index(1, 6), QStringLiteral("极耳间距"), Qt