Qt图形界面之树表结构

#Qt图形界面之树表结构

多年不写博客了,CSDN变化挺大的。
这里的实现的是一个树型控件的子结构是一个表。(本文用到的是一个treewidget和tableview)

效果在这里插入图片描述

一个简单的库

但是这个库是qt4版本的,修改了一部分,实现了在Qt5下可以使用,搜索ratbleheaderview可以自行下载也可以直接使用我的。

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=0);
RbTableHeaderItem(int arow, int acolumn, RbTableHeaderItem* parent=0);
~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;
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);
virtual Qt::ItemFlags flags(const QModelIndex &index) const;

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);
virtual QModelIndex indexAt(const QPoint&);
virtual void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const;
virtual QSize sectionSizeFromContents(int logicalIndex) const;

// 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 Q_SLOTS:
void onSectionResized(int logicalIdx,int oldSize,int newSize);

Q_SIGNALS:
void sectionPressed(int from, int to);

};

#endif /* RBTABLEHEADERVIEW_H_ */

RbTableHeaderView.cpp

#include “RbTableHeaderView.h”
#include < QPainter>
#include < QStandardItem>
#include < QMouseEvent>
#include < QVariant>
#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;

}

Qt::ItemFlags RbTableHeaderModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::ItemIsEnabled;
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
}

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(20);
}
else
{
baseSectionSize.setWidth(50);
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 (qVariantCanConvert<QBrush>(bg))
	//{
		sectionStyle.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(bg));
		sectionStyle.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(bg));
//	}
	//if (qVariantCanConvert<QBrush>(fg))
//	{
		//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;
}

/**

  • @return section numbers
    /
    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());
}

}

接下来就开始我 的表演了

自己创建一个继承Qwidget的类

#include <QtWidgets/QWidget>
#include “ui_QTreeViewAndQTableView.h”

#include < QTableView>
#include < QStandardItem>

#include < QTreeWidget>
#include < QHBoxLayout>
#include < QtCore/QTextCodec>
#include < QTreeView>
#include < QStandardItemModel>
#include < QTableView>
#include < QHeaderView>
#include < QFile>
#include < QMessageBox>
#include < QDebug>
#include < QComboBox>
#include < QBrush>

class QTreeViewAndQTableView : public QWidget
{
Q_OBJECT

public:
QTreeViewAndQTableView(QWidget *parent = Q_NULLPTR);

private:
Ui::QTreeViewAndQTableViewClass ui;

QTableView *m_pView;
QStandardItemModel *m_pModel;
QHeaderView *m_pHeadView;

};

.cpp如下所示

#include “QTreeViewAndQTableView.h”
#include “RbTableHeaderView.h”

QTreeViewAndQTableView::QTreeViewAndQTableView(QWidget *parent)
QWidget(parent),
m_pView(nullptr),
m_pModel(nullptr),
m_pHeadView(nullptr)
{
ui.setupUi(this);
QTreeWidget *tree = new QTreeWidget(this);  //树型控件

//树型控件的行表头的样式表
tree->header()->setStyleSheet("QHeaderView::section {background-color:#99CCCC;color: white;}");

tree->setColumnCount(12);  //设置12列
// 设置头标题
QStringList headers;
headers << "" << "" << QObject::tr("Input Method") << QObject::tr("Width\n(mm)") << QObject::tr("End Y\n(mm)") << "End Z\n(mm)" << "Member Type" << "Thinklove\n(mm)" << "Material" << "Aensing\nEffciency\n(%)" << "Shear\nEffciency\n(%)" << "Strake Name";
tree->setHeaderLabels(headers);  //设置树表头名称

tree->header()->setDefaultAlignment(Qt::AlignCenter);	// 表头居中对齐

QStringList treeRootItemHeader;
treeRootItemHeader << "" << "1" << "Gtith" << "2500" << "0" << "8460" << "Longitudinal Corrugated Bulkhead2" << "" << "" << "0" << "100" << "LCB1";
QTreeWidgetItem *rootItem = new QTreeWidgetItem(tree, treeRootItemHeader);  //树表的根项
QTreeWidgetItem *twoItem = new QTreeWidgetItem(tree, treeRootItemHeader);	//树表的第二个根项
for (int i = 0; i < 12; ++i)
{
	rootItem->setTextAlignment(i, Qt::AlignRight);  //居右对齐
	tree->resizeColumnToContents(i); //每一列的大小设为与内容相匹
	if (i == 7 || i == 8)
	{
		rootItem->setBackground(i, QBrush(QColor(Qt::lightGray)));  //背景置为灰色
		rootItem->setFlags(rootItem->flags() & (~Qt::ItemIsEditable));  //设置该字段不可修改
	}
	if (i == 11)
	{
		rootItem->setTextAlignment(i, Qt::AlignLeft);  //居左对齐
	}
}
tree->setColumnWidth(6, 250);  //设置第6列宽度为250

// 第2列添加QComboBox控件
QComboBox *pComBox = new QComboBox(tree);
QStringList texts;
texts << "Girth1" << "Girth2" << "Girth3";
pComBox->addItems(texts);
tree->setItemWidget(rootItem, 2, pComBox);

// 第6列添加QComboBox控件 
QComboBox *pComBoxSixColumn = new QComboBox(tree);
QStringList textsSixColumn;
textsSixColumn << "Longitudinal Corrugated Bulkhead" << "Longitudinal Corrugated Bulkhead2" << "Longitudinal Corrugated Bulkhead3";
pComBoxSixColumn->addItems(textsSixColumn);
tree->setItemWidget(rootItem, 6, pComBoxSixColumn);

//自定义视图
RbTableHeaderView* hHead = new RbTableHeaderView(Qt::Horizontal, 2, 4);

hHead->setSectionResizeMode(QHeaderView::Interactive);
hHead->setFixedHeight(40);

QAbstractItemModel* hModel = hHead->model();
hHead->setSpan(0, 1, 1, 2);  //合并单元格

hModel->setData(hModel->index(0, 1), QString("cell2"), Qt::DisplayRole);
hModel->setData(hModel->index(1, 1), QString("cell3"), Qt::DisplayRole);
hModel->setData(hModel->index(1, 2), QString("cell4"), Qt::DisplayRole);

for ( int i  = 0; i < 2; ++i)
{
	for ( int j = 0; j < 4; ++j)
	{			
		hHead->setCellBackgroundColor(hModel->index(i, j), QColor("#99CCCC"));	
		
	}
}

m_pView = new QTableView(this);   //创建tableview
m_pModel = new QStandardItemModel();  //表格的模型
//随机填写的数据
for (int i = 0; i < 5; ++i)
{
	m_pModel->setItem(i, 0, new QStandardItem("zhangsanfeng"));
	m_pModel->setItem(i, 1, new QStandardItem("20120202"));
	m_pModel->setItem(i, 2, new QStandardItem("male"));
	m_pModel->setItem(i, 3, new QStandardItem("18"));
	m_pModel->setItem(i, 4, new QStandardItem("tumu"));

}
//利用setModel()方法将数据模型与QTableView绑定
m_pView->setModel(m_pModel);
m_pView->setHorizontalHeader(hHead);

qApp->setStyleSheet("QTableCornerButton::section{background:#99CCCC;}");	//设置tableview横表头最左边的那个按钮颜色

QTreeWidgetItem *subRootItem = new QTreeWidgetItem;  //tree子项
tree->addTopLevelItem(rootItem);
rootItem->addChild(subRootItem); // 根添加一个子项
tree->setFirstItemColumnSpanned(subRootItem, true);  //该方法用于返回是否显示时项的第一列数据跨越所有列

tree->setItemWidget(subRootItem, 0, m_pView);  //子项的item是个table表

rootItem->addChild(twoItem);  //根添加第二个子项

// qss 设置
tree->setStyleSheet("QTreeView::branch:has-children:!has-siblings:closed,\
QTreeView::branch:closed:has-children:has-siblings{border-image: none; image: url(:/add.png);}\
QTreeView::branch:open:has-children:!has-siblings,\
QTreeView::branch:open:has-children:has-siblings{border-image: none; image: url(:/subtraction.png);}");

QHBoxLayout *pLayout = new QHBoxLayout(this);
pLayout->addWidget(tree);
setLayout(pLayout);
m_pView->resize(768, 768);

}
.

最后:小编调研不易,耗费很久才实现,谢谢大家支持。

bleCornerButton::section{background:#99CCCC;}");	//设置tableview横表头最左边的那个按钮颜色

	QTreeWidgetItem *subRootItem = new QTreeWidgetItem;  //tree子项
	tree->addTopLevelItem(rootItem);
	rootItem->addChild(subRootItem); // 根添加一个子项
	tree->setFirstItemColumnSpanned(subRootItem, true);  //该方法用于返回是否显示时项的第一列数据跨越所有列

	tree->setItemWidget(subRootItem, 0, m_pView);  //子项的item是个table表

	rootItem->addChild(twoItem);  //根添加第二个子项

	// qss 设置
	tree->setStyleSheet("QTreeView::branch:has-children:!has-siblings:closed,\
	QTreeView::branch:closed:has-children:has-siblings{border-image: none; image: url(:/add.png);}\
	QTreeView::branch:open:has-children:!has-siblings,\
	QTreeView::branch:open:has-children:has-siblings{border-image: none; image: url(:/subtraction.png);}");

	QHBoxLayout *pLayout = new QHBoxLayout(this);
	pLayout->addWidget(tree);
	setLayout(pLayout);
	m_pView->resize(768, 768);

}
.

最后:小编调研不易,耗费很久才实现,谢谢大家支持。
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值