QT-TableWidget多个行或者列合并效果

这篇具有很好参考价值的文章主要介绍了QT-TableWidget多个行或者列合并效果。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

使用代理,重新组合了行和列的合并,符合更多的实际应用场景,通过参数的方式,可以自定义设置想要的效果。

一、效果演示

tablewidget表头某一列弄成两列,Qt,qt,开发语言,ui

二、关键类

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(&sectionStyle);
		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,&sectionStyle.palette.brush(QPalette::Button));
		style()->drawControl(QStyle::CE_HeaderLabel, &sectionStyle, 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模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • qt设置tablewidget颜色、添加选择框、添加按钮和进度条

    添加选择框 在代码中设置tablewidget的样式表 设置表格,添加选择框 cellClicked事件响应,当点击表格项,对复选框进行选中和取消选择 添加进度条和按钮 设置表格 建立按钮和处理函数的信号槽连接,让按钮点击,进度条移动 槽函数和进度条控件 项目下载 https://download.csdn.n

    2024年02月11日
    浏览(58)
  • 【PyQt5】Qt Designer系列-----tableWidget部件设置使用教程

    注意不要选错部件tableView了!!! (1)选中tableWidget部件右键“编辑项目”打开 (2)设置行、列的间隔 (3)去掉行或列索引 (4)设置列左对齐或居中(默认居中) (5)设置标题之间的间隔 选中tableWidget部件右键“改变样式表” (1)设置选中显示背景颜色 (2)设置拉条

    2024年02月16日
    浏览(57)
  • QT 实现tablewidget整行的上下移动和双击编辑

    一、效果展示 二、实现方法 1、先对tablewidget设置 2、实现行的上下移动 主要实现方式是通过交换两行的数据来实现的 下面这两句主要实现选择行跟随移动的行

    2024年02月11日
    浏览(52)
  • tableWidget设置滚动条不显示问题

    参数设置 为什么我设置了滚动条却没有显示? 在一次项目开发中,我用到了QTableWidget,开发中采用了Qt中的UI设计师完成界面的布局设计,QTableWidget我设置了最小的宽 400,高200,但是我把主窗口缩小到很小,界面并没有显示滚动条,然后我就调用代码Qt::ScrollBarAlwaysOn 让滚动

    2024年02月11日
    浏览(52)
  • Python使用Pyside2和Qt Designer实现接口数据查询mainwindow-tablewidget和EXCEL导出功能,并生成EXE可执行文件直接调用.ui文件和生成py调用都有-初学

    通过Pyside2库调用QT Designer的UI文件,直接调用.ui文件和将.ui文件转换为.pt文件进行调用,调用测试成功生成exe文件 可以直接在终端调用 参考:https://blog.csdn.net/qq_44940689/article/details/123913832 直接在终端中运行 -F 只会生成单独的一个exe文件 -w 是双击exe不会打开黑色窗口,可以试

    2024年02月04日
    浏览(51)
  • pyqt 在tablewidget表格控件里添加 buttom按钮控件

       说明一下:在designer里!是没有办法再tablewidget的表格上添加其他控件了,按钮啊!标签啊!都不可以!你改样式表也没用! 所以只能再代码成面改了,你把.ui文件转成.py文件。在python文件里添加下面的代码就行!(要修改) 上面的代码都注释了,要改的会报错的,其他

    2024年02月13日
    浏览(38)
  • Excel简单宏定义(Microsoft 版)(快速合并多个表格,合并多个工作表,合并特定工作表)

    Excel简单宏定义(Microsoft 版)(快速合并多个表格,合并多个工作表,合并特定工作表) 1. 合并当前工作簿下的所有工作表 当前表格中有两个工作表为Sheet1和Sheet2,目的: 将两个表合并为一个表Sheet1 输入代码并运行 2. 合并当前目录下工作簿中特定工作表 当前目录下中有三个

    2024年02月11日
    浏览(41)
  • Git提交单个或者多个文件

    Git提交指定文件步骤 1.git status //查看修改的所有内容(或者git status -s) 2.git add ’ ’,例如:(git add components/pages/holders/xxx.vue) //’ \\\'引号中间放上文件名,执行上一步后,会显示文件名跟目录 //多个文件用空格分开 3.git stash -u -k //忽略其他文件,很重要的一步!!!! 4.gi

    2024年02月01日
    浏览(50)
  • 怎么合并多个视频?简单视频合并方法分享

    合并多个视频可以将它们组合成一个更长的视频,这对于需要播放多个短视频的情况非常有用。此外,合并视频还可以使视频编辑过程更加高效,因为不必将多个独立的视频文件分别处理。最后,合并视频可以减少文件数量,从而使整个视频集合更加整洁和易于管理。下面给

    2024年02月14日
    浏览(51)
  • sql语句两个字段合并或者两个字段拼接显示

    mysql 使用 concat函数 小栗子: sql server 连接字段,直接使用 + 号,和java字符串拼接一样 小栗子: oracle 数据库 可以使用 || ,也可以使用 concat函数 小栗子: ACCESS数据库连接字段,使用 + 号,他与sql server 一样的 小栗子:

    2024年02月11日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包