1.效果如下。
2.实现原理
使用Qt的代理机制去绘制列表的菜单项。
3.代码如下
代理类 ccstyleditemdelegate.cpp
#include "ccstyleditemdelegate.h"
#include <QDebug>
CCStyledItemDelegate::CCStyledItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
//列表右侧图标
m_expandIconName = QString::fromLocal8Bit(":/Image/信号列表-上拉.png");
m_collapseIconName = QString::fromLocal8Bit(":/Image/信号列表-下拉.png");
}
CCStyledItemDelegate::~CCStyledItemDelegate()
{
}
void CCStyledItemDelegate::setTreeView(QTreeView *treeView)
{
//把调用代理类的QTreeView传递进来,这样,QTreeView类的节点展开和关闭信号,就可以在代理类的槽中进行处理。
m_treeView = treeView;
connect(this,SIGNAL(expanded(const QModelIndex &,bool)),this,SLOT(onExpandedTree(const QModelIndex &,bool)));
}
void CCStyledItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//节点项的绘制,option表示节点项,index表示节点,index.data()表示节点的数据。
QString str= index.data(Qt::DisplayRole).toString();
if(str=="AA") //节点数据等于 "AA"
{
painter->setBrush(Qt::gray);
painter->drawRect(QRect(option.rect));
QRect textAARect = QRect(option.rect.x()+20,option.rect.y(),option.rect.width(),option.rect.height());
painter->drawText(textAARect,Qt::AlignLeft|Qt::AlignVCenter,str);
}
QString strChild= index.child(0,0).data(Qt::DisplayRole).toString();
if(str=="ONE")
{
painter->setBrush(Qt::gray);
painter->drawRect(QRect(option.rect));
QRect textONERect = QRect(option.rect.x()+17,option.rect.y(),option.rect.width(),option.rect.height());
painter->drawText(textONERect,Qt::AlignLeft|Qt::AlignVCenter,str);
}
if(str=="BB")
{
painter->setBrush(Qt::gray);
painter->drawRect(QRect(option.rect));
QRect textBBRect = QRect(option.rect.x()+40,option.rect.y(),option.rect.width(),option.rect.height());
painter->drawText(textBBRect,Qt::AlignLeft|Qt::AlignVCenter,str);
}
if(str=="CC")
{
painter->setBrush(Qt::gray);
painter->drawRect(QRect(option.rect));
QRect textCCRect = QRect(option.rect.x()+60,option.rect.y(),option.rect.width(),option.rect.height());
painter->drawText(textCCRect,Qt::AlignLeft|Qt::AlignVCenter,str);
}
bool bExpanded = true;
if (m_treeView != NULL)
{
bExpanded = m_treeView->isExpanded(index);//节点展开状态,如果展开为true,否则为false。
}
const QStandardItemModel *model = (QStandardItemModel*)index.model();//获取节点的模型model
if (model->hasChildren(index)){//模型调用hasChildren,判断当前节点是否有子节点。有为true
int height = (option.rect.height() - m_pixmapWidth) / 2;
QPixmap pixmap = bExpanded ? QPixmap(m_expandIconName) : QPixmap(m_collapseIconName);
QRect decorationRect = QRect(option.rect.left() + option.rect.width() - 30, option.rect.top() + height, m_pixmapWidth, m_pixmapHeight);
painter->drawPixmap(decorationRect, pixmap);
}
}
void CCStyledItemDelegate::onExpandedTree(const QModelIndex &index, bool isExpanded)
{
if(m_treeView !=NULL)
{
m_treeView->setExpanded(index,isExpanded);
}
}
QSize CCStyledItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QSize(500,50);
}
bool CCStyledItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
if (event->type() == QEvent::MouseButtonPress )
{
bool bExpanded = m_treeView->isExpanded(index);
emit expanded(index,!bExpanded);
}
return true;
}