前言
使用代理,重新组合了行和列的合并,符合更多的实际应用场景,通过参数的方式,可以自定义设置想要的效果。
一、效果演示
文章来源:https://www.toymoban.com/news/detail-613096.html
二、关键类
1.头文件
#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
};
class RbTableHeaderItem
{
public:
RbTableHeaderItem(RbTableHeaderItem* parent=0);
RbTableHeaderItem(int arow, int acolumn, RbTableHeaderItem* parent=0);
~RbTableHeaderItem();
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:
int row_prop;
int column_prop;
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:
virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const;
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return row_count_prop; }
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return column_count_prop;}
virtual QVariant data(const QModelIndex &index, int role) const;
virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
private:
int row_count_prop;
int column_count_prop;
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:
virtual void mousePressEvent(QMouseEvent* event);
virtual QModelIndex indexAt(const QPoint&);
virtual void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const;
virtual QSize sectionSizeFromContents(int logicalIndex) const;
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 Q_SLOTS:
void onSectionResized(int logicalIdx,int oldSize,int newSize);
Q_SIGNALS:
void sectionPressed(int from, int to);
};
#endif /* RBTABLEHEADERVIEW_H_ */
2.源文件
#include "RbTableHeaderView.h"
#include <QPainter>
#include <QStandardItem>
#include <QMouseEvent>
#include <qdrawutil.h>
RbTableHeaderItem::RbTableHeaderItem(RbTableHeaderItem* parent):
row_prop(0),column_prop(0),parent_item(parent)
{
}
RbTableHeaderItem::RbTableHeaderItem(int arow, int acolumn, RbTableHeaderItem* parent):
row_prop(arow),column_prop(acolumn),parent_item(parent)
{
}
RbTableHeaderItem::~RbTableHeaderItem()
{
}
RbTableHeaderItem* RbTableHeaderItem::insertChild(int row, int col)
{
RbTableHeaderItem* newChild = new RbTableHeaderItem(row,col,this);
child_items.insert(QPair<int,int>(row,col),newChild);
return newChild;
}
const RbTableHeaderItem* RbTableHeaderItem::child(int row,int col) const
{
QHash<QPair<int,int>,RbTableHeaderItem*>::const_iterator itr = child_items.find(QPair<int,int>(row,col));
if (itr != child_items.end()) return itr.value();
return 0;
}
RbTableHeaderItem* RbTableHeaderItem::child(int row,int col)
{
QHash<QPair<int,int>,RbTableHeaderItem*>::iterator itr = child_items.find(QPair<int,int>(row,col));
if (itr != child_items.end()) return itr.value();
return 0;
}
void RbTableHeaderItem::setText(const QString& text)
{
role_datas.insert(Qt::DisplayRole,text);
}
QVariant RbTableHeaderItem::data(int role) const
{
QHash<int,QVariant>::const_iterator itr = role_datas.find(role);
if (itr != role_datas.end()) return itr.value();
return QVariant();
}
void RbTableHeaderItem::setData(const QVariant& data, int role)
{
role_datas.insert(role,data);
}
void RbTableHeaderItem::clear()
{
QList<RbTableHeaderItem*> items = child_items.values();
foreach (RbTableHeaderItem* item, child_items)
{
if (item) delete item;
}
child_items.clear();
}
RbTableHeaderModel::RbTableHeaderModel(int rows, int cols, QObject* parent) :
QAbstractTableModel(parent),row_count_prop(rows),column_count_prop(cols),root_item(new RbTableHeaderItem())
{
}
RbTableHeaderModel::~RbTableHeaderModel()
{
root_item->clear();
delete root_item;
}
QModelIndex RbTableHeaderModel::index(int row, int column, const QModelIndex & parent) const
{
if (!hasIndex(row,column,parent)) return QModelIndex();
RbTableHeaderItem* parentItem;
if (!parent.isValid()) parentItem = root_item; // parent item is always the root_item on table model
else parentItem = static_cast<RbTableHeaderItem*>(parent.internalPointer()); // no effect
RbTableHeaderItem* childItem = parentItem->child(row,column);
if (!childItem) childItem = parentItem->insertChild(row,column);
return createIndex(row,column,childItem);
return QModelIndex();
}
QVariant RbTableHeaderModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.row() >= row_count_prop || index.row() < 0 || index.column() >= column_count_prop || index.column() < 0)
return QVariant();
RbTableHeaderItem* item = static_cast<RbTableHeaderItem*>(index.internalPointer());
return item->data(role);
}
bool RbTableHeaderModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
if (index.isValid())
{
RbTableHeaderItem* item = static_cast<RbTableHeaderItem*>(index.internalPointer());
if (role == COLUMN_SPAN_ROLE)
{
int col = index.column();
int span = value.toInt();
if (span > 0) // span size should be more than 1, else nothing to do
{
if (col+span-1 >= column_count_prop) // span size should be less than whole columns,
span = column_count_prop-col;
item->setData(span,COLUMN_SPAN_ROLE);
}
}
else if (role == ROW_SPAN_ROLE)
{
int row = index.row();
int span = value.toInt();
if (span > 0) // span size should be more than 1, else nothing to do
{
if (row+span-1 >= row_count_prop)
span = row_count_prop-row;
item->setData(span,ROW_SPAN_ROLE);
}
}
else
item->setData(value,role);
return true;
}
return false;
}
RbTableHeaderView::RbTableHeaderView(Qt::Orientation orientation, int rows, int columns, QWidget* parent):
QHeaderView(orientation,parent)
{
QSize baseSectionSize;
if (orientation == Qt::Horizontal)
{
baseSectionSize.setWidth(defaultSectionSize());
baseSectionSize.setHeight(30);
}
else
{
baseSectionSize.setWidth(60);
baseSectionSize.setHeight(defaultSectionSize());
}
// create header model
RbTableHeaderModel* headerModel = new RbTableHeaderModel(rows,columns);
// set default size of item
for (int row=0;row<rows;++row)
for (int col=0;col<columns;++col)
headerModel->setData(headerModel->index(row,col),baseSectionSize,Qt::SizeHintRole);
setModel(headerModel);
connect(this, SIGNAL(sectionResized(int, int, int)), this, SLOT(onSectionResized(int,int,int)));
}
RbTableHeaderView::~RbTableHeaderView()
{
}
void RbTableHeaderView::setRowHeight(int row, int rowHeight)
{
RbTableHeaderModel* md = qobject_cast<RbTableHeaderModel*>(model());
const int cols = md->columnCount();
for (int col=0;col<cols;++col)
{
QSize sz = md->index(row,col).data(Qt::SizeHintRole).toSize();
sz.setHeight(rowHeight);
md->setData(md->index(row,col),sz,Qt::SizeHintRole);
}
if (orientation() == Qt::Vertical)
resizeSection(row,rowHeight);
}
void RbTableHeaderView::setColumnWidth(int col, int colWidth)
{
RbTableHeaderModel* md = qobject_cast<RbTableHeaderModel*>(model());
const int rows = md->rowCount();
for (int row=0;row<rows;++row)
{
QSize sz = md->index(row,col).data(Qt::SizeHintRole).toSize();
sz.setWidth(colWidth);
md->setData(md->index(row,col),sz,Qt::SizeHintRole);
}
if (orientation() == Qt::Horizontal)
resizeSection(col,colWidth);
}
void RbTableHeaderView::setSpan(int row, int column, int rowSpanCount, int columnSpanCount)
{
RbTableHeaderModel* md = qobject_cast<RbTableHeaderModel*>(model());
QModelIndex idx = md->index(row,column);
if (rowSpanCount > 0)
md->setData(idx,rowSpanCount,ROW_SPAN_ROLE);
if (columnSpanCount)
md->setData(idx,columnSpanCount,COLUMN_SPAN_ROLE);
}
void RbTableHeaderView::setCellBackgroundColor(const QModelIndex& index, const QColor& color)
{
RbTableHeaderModel* md = qobject_cast<RbTableHeaderModel*>(model());
md->setData(index,color,Qt::BackgroundRole);
}
void RbTableHeaderView::setCellForegroundColor(const QModelIndex& index, const QColor& color)
{
RbTableHeaderModel* md = qobject_cast<RbTableHeaderModel*>(model());
md->setData(index,color,Qt::ForegroundRole);
}
void RbTableHeaderView::mousePressEvent(QMouseEvent* event)
{
QHeaderView::mousePressEvent(event);
QPoint pos = event->pos();
QModelIndex index = indexAt(pos);
const int OTN = orientation();
if (index.isValid())
{
int beginSection = -1;
int endSection = -1;
int numbers = 0;
numbers = getSectionRange(index,&beginSection,&endSection);
if (numbers > 0)
{
emit sectionPressed(beginSection,endSection);
return;
}
else
{
const RbTableHeaderModel* tblModel = qobject_cast<RbTableHeaderModel*>(this->model());
const int LEVEL_CNT = (OTN == Qt::Horizontal)?tblModel->rowCount():tblModel->columnCount();
int logicalIdx = (OTN == Qt::Horizontal)?index.column():index.row();
int curLevel = (OTN == Qt::Horizontal)?index.row():index.column();
for (int i=0;i<LEVEL_CNT;++i)
{
QModelIndex cellIndex = (OTN == Qt::Horizontal)?tblModel->index(i,logicalIdx):tblModel->index(logicalIdx,i);
numbers = getSectionRange(cellIndex,&beginSection,&endSection);
if (numbers > 0)
{
if (beginSection <= logicalIdx && logicalIdx <= endSection)
{
int beginLevel = (OTN == Qt::Horizontal)?cellIndex.row():cellIndex.column();
QVariant levelSpanCnt = cellIndex.data((OTN == Qt::Horizontal)?ROW_SPAN_ROLE:COLUMN_SPAN_ROLE);
if (!levelSpanCnt.isValid())
continue;
int endLevel = beginLevel + levelSpanCnt.toInt()-1;
if (beginLevel <= curLevel && curLevel <= endLevel)
{
emit sectionPressed(beginSection,endSection);
break;
}
}
}
}
}
}
}
QModelIndex RbTableHeaderView::indexAt(const QPoint& pos)
{
const RbTableHeaderModel* tblModel = qobject_cast<RbTableHeaderModel*>(this->model());
const int OTN = orientation();
const int ROWS = tblModel->rowCount();
const int COLS = tblModel->columnCount();
int logicalIdx = logicalIndexAt(pos);
if (OTN == Qt::Horizontal)
{
int dY=0;
for (int row=0;row<ROWS;++row)
{
QModelIndex cellIndex = tblModel->index(row,logicalIdx);
dY += cellIndex.data(Qt::SizeHintRole).toSize().height();
if (pos.y() <= dY) return cellIndex;
}
}
else
{
int dX=0;
for (int col=0;col<COLS;++col)
{
QModelIndex cellIndex = tblModel->index(logicalIdx,col);
dX += cellIndex.data(Qt::SizeHintRole).toSize().width();
if (pos.x() <= dX) return cellIndex;
}
}
return QModelIndex();
}
void RbTableHeaderView::paintSection(QPainter* painter, const QRect& rect, int logicalIdx) const
{
const RbTableHeaderModel* tblModel = qobject_cast<RbTableHeaderModel*>(this->model());
const int OTN = orientation();
const int LEVEL_CNT = (OTN == Qt::Horizontal)?tblModel->rowCount():tblModel->columnCount();
for (int i=0;i<LEVEL_CNT;++i)
{
QModelIndex cellIndex = (OTN == Qt::Horizontal)?tblModel->index(i,logicalIdx):tblModel->index(logicalIdx,i);
QSize cellSize=cellIndex.data(Qt::SizeHintRole).toSize();
QRect sectionRect(rect);
// set position of the cell
if (OTN == Qt::Horizontal)
sectionRect.setTop(rowSpanSize(logicalIdx,0,i)); // distance from 0 to i-1 rows
else
sectionRect.setLeft(columnSpanSize(logicalIdx,0,i));
sectionRect.setSize(cellSize);
// check up span column or row
QModelIndex colSpanIdx = columnSpanIndex(cellIndex);
QModelIndex rowSpanIdx = rowSpanIndex(cellIndex);
if (colSpanIdx.isValid())
{
int colSpanFrom = colSpanIdx.column();
int colSpanCnt = colSpanIdx.data(COLUMN_SPAN_ROLE).toInt();
int colSpanTo = colSpanFrom+colSpanCnt-1;
int colSpan = columnSpanSize(cellIndex.row(),colSpanFrom,colSpanCnt);
if (OTN == Qt::Horizontal)
sectionRect.setLeft(sectionViewportPosition(colSpanFrom));
else
{
sectionRect.setLeft(columnSpanSize(logicalIdx,0,colSpanFrom));
i = colSpanTo;
}
sectionRect.setWidth(colSpan);
// check up if the column span index has row span
QVariant subRowSpanData = colSpanIdx.data(ROW_SPAN_ROLE);
if (subRowSpanData.isValid())
{
int subRowSpanFrom = colSpanIdx.row();
int subRowSpanCnt = subRowSpanData.toInt();
int subRowSpanTo = subRowSpanFrom+subRowSpanCnt-1;
int subRowSpan = rowSpanSize(colSpanFrom,subRowSpanFrom,subRowSpanCnt);
if (OTN == Qt::Vertical)
sectionRect.setTop(sectionViewportPosition(subRowSpanFrom));
else
{
sectionRect.setTop(rowSpanSize(colSpanFrom,0,subRowSpanFrom));
i = subRowSpanTo;
}
sectionRect.setHeight(subRowSpan);
}
cellIndex=colSpanIdx;
}
if (rowSpanIdx.isValid())
{
int rowSpanFrom = rowSpanIdx.row();
int rowSpanCnt = rowSpanIdx.data(ROW_SPAN_ROLE).toInt();
int rowSpanTo = rowSpanFrom+rowSpanCnt-1;
int rowSpan = rowSpanSize(cellIndex.column(),rowSpanFrom,rowSpanCnt);
if (OTN == Qt::Vertical)
sectionRect.setTop(sectionViewportPosition(rowSpanFrom));
else
{
sectionRect.setTop(rowSpanSize(logicalIdx,0,rowSpanFrom));
i = rowSpanTo;
}
sectionRect.setHeight(rowSpan);
// check up if the row span index has column span
QVariant subColSpanData = rowSpanIdx.data(COLUMN_SPAN_ROLE);
if (subColSpanData.isValid())
{
int subColSpanFrom = rowSpanIdx.column();
int subColSpanCnt = subColSpanData.toInt();
int subColSpanTo = subColSpanFrom+subColSpanCnt-1;
int subColSpan = columnSpanSize(rowSpanFrom,subColSpanFrom,subColSpanCnt);
if (OTN == Qt::Horizontal)
sectionRect.setLeft(sectionViewportPosition(subColSpanFrom));
else
{
sectionRect.setLeft(columnSpanSize(rowSpanFrom,0,subColSpanFrom));
i = subColSpanTo;
}
sectionRect.setWidth(subColSpan);
}
cellIndex=rowSpanIdx;
}
// draw section with style
QStyleOptionHeader sectionStyle;
initStyleOption(§ionStyle);
sectionStyle.textAlignment = Qt::AlignCenter;
sectionStyle.iconAlignment = Qt::AlignVCenter;
sectionStyle.section = logicalIdx;
sectionStyle.text = cellIndex.data(Qt::DisplayRole).toString();
sectionStyle.rect = sectionRect;
// file background or foreground color of the cell
QVariant bg = cellIndex.data(Qt::BackgroundRole);
QVariant fg = cellIndex.data(Qt::ForegroundRole);
if (bg.canConvert(QMetaType::QBrush))
{
sectionStyle.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(bg));
sectionStyle.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(bg));
}
if (fg.canConvert(QMetaType::QBrush))
{
sectionStyle.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(fg));
}
painter->save();
qDrawShadePanel(painter,sectionStyle.rect,sectionStyle.palette,false,1,§ionStyle.palette.brush(QPalette::Button));
style()->drawControl(QStyle::CE_HeaderLabel, §ionStyle, painter);
painter->restore();
}
}
QSize RbTableHeaderView::sectionSizeFromContents(int logicalIndex) const
{
const RbTableHeaderModel* tblModel = qobject_cast<const RbTableHeaderModel*>(this->model());
const int OTN = orientation();
const int LEVEL_CNT = (OTN == Qt::Horizontal)?tblModel->rowCount():tblModel->columnCount();
QSize siz = QHeaderView::sectionSizeFromContents(logicalIndex);
for (int i=0;i<LEVEL_CNT;++i)
{
QModelIndex cellIndex = (OTN == Qt::Horizontal)?tblModel->index(i,logicalIndex):tblModel->index(logicalIndex,i);
QModelIndex colSpanIdx = columnSpanIndex(cellIndex);
QModelIndex rowSpanIdx = rowSpanIndex(cellIndex);
siz=cellIndex.data(Qt::SizeHintRole).toSize();
if (colSpanIdx.isValid())
{
int colSpanFrom = colSpanIdx.column();
int colSpanCnt = colSpanIdx.data(COLUMN_SPAN_ROLE).toInt();
int colSpanTo = colSpanFrom + colSpanCnt -1;
siz.setWidth(columnSpanSize(colSpanIdx.row(),colSpanFrom,colSpanCnt));
if (OTN == Qt::Vertical) i = colSpanTo;
}
if (rowSpanIdx.isValid())
{
int rowSpanFrom = rowSpanIdx.row();
int rowSpanCnt = rowSpanIdx.data(ROW_SPAN_ROLE).toInt();
int rowSpanTo = rowSpanFrom + rowSpanCnt-1;
siz.setHeight(rowSpanSize(rowSpanIdx.column(),rowSpanFrom,rowSpanCnt));
if (OTN == Qt::Horizontal) i = rowSpanTo;
}
}
return siz;
}
QModelIndex RbTableHeaderView::columnSpanIndex(const QModelIndex& currentIdx) const
{
const RbTableHeaderModel* tblModel = qobject_cast<RbTableHeaderModel*>(model());
const int curRow = currentIdx.row();
const int curCol = currentIdx.column();
int i = curCol;
while (i >= 0)
{
QModelIndex spanIndex = tblModel->index(curRow,i);
QVariant span = spanIndex.data(COLUMN_SPAN_ROLE);
if (span.isValid() && spanIndex.column()+span.toInt()-1 >= curCol)
return spanIndex;
i--;
}
return QModelIndex();
}
QModelIndex RbTableHeaderView::rowSpanIndex(const QModelIndex& currentIdx) const
{
const RbTableHeaderModel* tblModel = qobject_cast<RbTableHeaderModel*>(model());
const int curRow = currentIdx.row();
const int curCol = currentIdx.column();
int i = curRow;
while (i >= 0)
{
QModelIndex spanIndex = tblModel->index(i,curCol);
QVariant span = spanIndex.data(ROW_SPAN_ROLE);
if (span.isValid() && spanIndex.row()+span.toInt()-1 >= curRow)
return spanIndex;
i--;
}
return QModelIndex();
}
int RbTableHeaderView::columnSpanSize(int row, int from, int spanCount) const
{
const RbTableHeaderModel* tblModel = qobject_cast<RbTableHeaderModel*>(model());
int span = 0;
for (int i=from;i<from+spanCount;++i)
{
QSize cellSize = tblModel->index(row,i).data(Qt::SizeHintRole).toSize();
span += cellSize.width();
}
return span;
}
int RbTableHeaderView::rowSpanSize(int column, int from, int spanCount) const
{
const RbTableHeaderModel* tblModel = qobject_cast<RbTableHeaderModel*>(model());
int span = 0;
for (int i=from;i<from+spanCount;++i)
{
QSize cellSize = tblModel->index(i,column).data(Qt::SizeHintRole).toSize();
span += cellSize.height();
}
return span;
}
int RbTableHeaderView::getSectionRange(QModelIndex& index, int* beginSection, int* endSection) const
{
// check up section range from the index
QModelIndex colSpanIdx = columnSpanIndex(index);
QModelIndex rowSpanIdx = rowSpanIndex(index);
if (colSpanIdx.isValid())
{
int colSpanFrom = colSpanIdx.column();
int colSpanCnt = colSpanIdx.data(COLUMN_SPAN_ROLE).toInt();
int colSpanTo = colSpanFrom+colSpanCnt-1;
if (orientation() == Qt::Horizontal)
{
*beginSection = colSpanFrom;
*endSection = colSpanTo;
index = colSpanIdx;
return colSpanCnt;
}
else
{
// check up if the column span index has row span
QVariant subRowSpanData = colSpanIdx.data(ROW_SPAN_ROLE);
if (subRowSpanData.isValid())
{
int subRowSpanFrom = colSpanIdx.row();
int subRowSpanCnt = subRowSpanData.toInt();
int subRowSpanTo = subRowSpanFrom+subRowSpanCnt-1;
*beginSection = subRowSpanFrom;
*endSection = subRowSpanTo;
index = colSpanIdx;
return subRowSpanCnt;
}
}
}
if (rowSpanIdx.isValid())
{
int rowSpanFrom = rowSpanIdx.row();
int rowSpanCnt = rowSpanIdx.data(ROW_SPAN_ROLE).toInt();
int rowSpanTo = rowSpanFrom+rowSpanCnt-1;
if (orientation() == Qt::Vertical)
{
*beginSection = rowSpanFrom;
*endSection = rowSpanTo;
index = rowSpanIdx;
return rowSpanCnt;
}
else
{
// check up if the row span index has column span
QVariant subColSpanData = rowSpanIdx.data(COLUMN_SPAN_ROLE);
if (subColSpanData.isValid())
{
int subColSpanFrom = rowSpanIdx.column();
int subColSpanCnt = subColSpanData.toInt();
int subColSpanTo = subColSpanFrom+subColSpanCnt-1;
*beginSection = subColSpanFrom;
*endSection = subColSpanTo;
index = rowSpanIdx;
return subColSpanCnt;
}
}
}
return 0;
}
void RbTableHeaderView::onSectionResized(int logicalIndex,int oldSize,int newSize)
{
RbTableHeaderModel* tblModel = qobject_cast<RbTableHeaderModel*>(this->model());
const int OTN = orientation();
const int LEVEL_CNT = (OTN == Qt::Horizontal)?tblModel->rowCount():tblModel->columnCount();
int pos = sectionViewportPosition(logicalIndex);
int xx = (OTN == Qt::Horizontal)?pos:0;
int yy = (OTN == Qt::Horizontal)?0:pos;
QRect sectionRect(xx,yy,0,0);
for (int i=0;i<LEVEL_CNT;++i)
{
QModelIndex cellIndex = (OTN == Qt::Horizontal)?tblModel->index(i,logicalIndex):tblModel->index(logicalIndex,i);
QSize cellSize=cellIndex.data(Qt::SizeHintRole).toSize();
// set position of cell
if (OTN == Qt::Horizontal)
{
sectionRect.setTop(rowSpanSize(logicalIndex,0,i));
cellSize.setWidth(newSize);
}
else
{
sectionRect.setLeft(columnSpanSize(logicalIndex,0,i));
cellSize.setHeight(newSize);
}
tblModel->setData(cellIndex,cellSize,Qt::SizeHintRole);
QModelIndex colSpanIdx = columnSpanIndex(cellIndex);
QModelIndex rowSpanIdx = rowSpanIndex(cellIndex);
if (colSpanIdx.isValid())
{
int colSpanFrom = colSpanIdx.column();
if (OTN == Qt::Horizontal)
sectionRect.setLeft(sectionViewportPosition(colSpanFrom));
else
{
sectionRect.setLeft(columnSpanSize(logicalIndex,0,colSpanFrom));
}
}
if (rowSpanIdx.isValid())
{
int rowSpanFrom = rowSpanIdx.row();
if (OTN == Qt::Vertical)
sectionRect.setTop(sectionViewportPosition(rowSpanFrom));
else
sectionRect.setTop(rowSpanSize(logicalIndex,0,rowSpanFrom));
}
QRect rToUpdate(sectionRect);
rToUpdate.setWidth(viewport()->width()-sectionRect.left());
rToUpdate.setHeight(viewport()->height()-sectionRect.top());
viewport()->update(rToUpdate.normalized());
}
}
3.应用程使用
#include "CTableView.h"
#include <QDebug>
CTableView::CTableView(QWidget *parent) :
QWidget(parent)
{
}
CTableView::~CTableView()
{
}
// nWorkPiece:工件数量
// nProcessCount:工序数量
// nMachineCount:机器数量
QTableView* CTableView::createTableView(int nWorkPiece, int nProcessCount, int nMachineCount)
{
if(nWorkPiece == 0 || nProcessCount == 0|| nMachineCount == 0)
{
return m_pTableView;
}
if (m_pHHead != nullptr)
{
delete m_pHHead;
m_pHHead = nullptr;
}
if (m_pVHead != nullptr)
{
delete m_pVHead;
m_pVHead = nullptr;
}
if (m_pHModel != nullptr)
{
delete m_pHModel;
m_pHModel = nullptr;
}
if (m_pVModel != nullptr)
{
delete m_pVModel;
m_pVModel = nullptr;
}
if (m_pDataModel != nullptr)
{
delete m_pDataModel;
m_pDataModel = nullptr;
}
if (m_pTableView != nullptr)
{
delete m_pTableView;
m_pTableView = nullptr;
}
m_nWorkPiece= nWorkPiece;
m_nProcessCount = nProcessCount;
m_nMachineCount = nMachineCount;
m_pHHead = new RbTableHeaderView(Qt::Horizontal, 2, 1 + nMachineCount);
m_pVHead = new RbTableHeaderView(Qt::Vertical, nProcessCount*nWorkPiece, 1);
m_pHModel = m_pHHead->model();
m_pVModel = m_pVHead->model();
m_pDataModel = new QStandardItemModel();
m_pTableView = new QTableView();
m_pHHead->setSpan(0, 0, 2, 1);
m_pHHead->setSpan(0, 1, 1, 1 + nMachineCount);
m_pHModel->setData(m_pHModel->index(0, 0), QString(u8"工具"), Qt::DisplayRole);
m_pHModel->setData(m_pHModel->index(0, 1), QString(u8"显示可变化内容"), Qt::DisplayRole);
QFont font("Microsoft YaHei", 10);
// 机器名称
for(int i = 1; i <= nMachineCount; i++)
{
m_pHHead->setSpan(1, i, 1, 1);
m_pHModel->setData(m_pHModel->index(1, i), QString("T%1").arg(i), Qt::DisplayRole);
}
// 工件名称
for (int i = 0; i < nWorkPiece; i++)
{
m_pVHead->setSpan(i*nProcessCount, 0, nProcessCount, 1);
m_pVModel->setData(m_pVModel->index(i*nProcessCount, 0), QString("NO.%1").arg(i+1), Qt::DisplayRole);
}
// 初始化空值
for (int iRow = 0; iRow < (nWorkPiece*nProcessCount); iRow++)
{
for (int iCol = 0; iCol < (nMachineCount + 1); iCol++)
{
auto pItem = new QStandardItem(QString(""));
pItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
m_pDataModel->setItem(iRow, iCol, pItem);
if (iCol == 0 )
m_pDataModel->item(iRow, 0)->setFont(font);
}
}
// 工序名称
for (int iWork = 0 ; iWork < nWorkPiece; iWork++)
{
for (int iProcess = 0; iProcess < nProcessCount; iProcess++)
m_pDataModel->item(iWork*nProcessCount + iProcess, 0)->setText(QString("O%1%2").arg(iWork + 1).arg(iProcess + 1));
}
m_pHHead->setSectionsClickable(true);
m_pVHead->setSectionsClickable(true);
m_pTableView->setModel(m_pDataModel);
m_pTableView->setHorizontalHeader(m_pHHead);
m_pTableView->setVerticalHeader(m_pVHead);
m_pTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
m_pTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
m_pTableView->horizontalHeader()->setFont(font);
m_pTableView->verticalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
m_pTableView->verticalHeader()->setFont(font);
return m_pTableView;
}
bool CTableView::getData(QList<sTbData>& tbDataList)
{
if(m_nWorkPiece == 0|| m_nMachineCount == 0|| m_nProcessCount == 0)
return false;
// 追加工件数
for(int i = 0; i < m_nWorkPiece; i++)
{
sTbData tbData;
tbData.strPieceName = QString("J%1").arg(i+1);
tbDataList << tbData;
}
int nRowCount = m_nWorkPiece*m_nProcessCount;
for(int iRow = 0; iRow < nRowCount; iRow++)
{
int nIndex = iRow % m_nProcessCount;
if(nIndex < tbDataList.size())
{
sTbItem tbItem;
for(int jCol = 0; jCol < m_nMachineCount+1; jCol++)
{
QString strText = m_pDataModel->item(iRow,jCol)->text();
//qDebug() << QString("text R%1-C%2 = %3").arg(iRow).arg(jCol).arg(strText) << "\n";
if(jCol == 0)
{
// 工序名称
tbItem.strProcessName = strText;
}
else
{
if(strText.isEmpty() || strText == D_NONE_VALUE || strText == "-")
{
// 无效值
tbItem.dValueList<< D_NONE_VALUE;
}
else
{
tbItem.dValueList<< strText.toDouble();
}
}
}
tbDataList[nIndex].tbItemList << tbItem;
}
}
return true;
}
void CTableView::setData(QList<sTbData> tbDataList)
{
if(m_nWorkPiece == 0
|| m_nMachineCount == 0
|| m_nProcessCount == 0
|| tbDataList.size() == 0)
{
return ;
}
int nRowCount = m_nWorkPiece*m_nProcessCount;
for(int iRow = 0; iRow < nRowCount; iRow++)
{
int nIndex = iRow % m_nProcessCount;
if(nIndex < tbDataList.size())
{
int nIndexItem = (iRow/m_nProcessCount) % m_nProcessCount;
for(int jCol = 0; jCol < m_nMachineCount+1; jCol++)
{
if (nIndexItem >= tbDataList[nIndex].tbItemList.size())
{
continue;
}
if(jCol < tbDataList[nIndex].tbItemList[nIndexItem].dValueList.size()
&& nIndexItem < m_nProcessCount)
{
QString strText = "";
double dValue = tbDataList[nIndex].tbItemList[nIndexItem].dValueList[jCol];
if((int)dValue == D_NONE_VALUE)
{
// 无效值
strText = "-";
}
else
{
strText= QString("%1").arg(dValue);
}
if((jCol+1) < m_pDataModel->columnCount())
{
m_pDataModel->item(iRow, jCol+1)->setText(strText);
}
}
}
}
}
}
三、程序下载
https://download.csdn.net/download/u013083044/86784759文章来源地址https://www.toymoban.com/news/detail-613096.html
到了这里,关于QT-TableWidget多个行或者列合并效果的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!