制垂直线。绘制的竖线是否绘制到底,取决于是否有向下的兄弟
有爷爷的节点可能需要额外绘制向下的竖线。是否绘制取决于自己的父亲是否有向下的兄弟
规则3其实是一个循环的处理,也就是说爷爷如果有爸爸,也就是说节点如果有祖爷爷,那么可能还需要绘制更多的向下竖线。是否绘制取决于节点的爷爷是否有向下的兄弟
代码这里就不细说了,有兴趣的可以自己研究研究。绘制规则就是上述4点
//绘制branch
{
DataNode * node = static_cast<DataNode *>(index.internalPointer());
bool hasChild = node->children().size() != 0;//是否有孩子
QList<DataNode *> & children = node->parent()->children();
bool has_next_siblings = children.indexOf(node) != (children.size() - 1);//是否有向后的兄弟
bool has_pre_siblings = children.indexOf(node) != 0;//是否有向前的兄弟
int level = node->level();
int indentaion = indentation();//缩进
int indentaions = indentaion * (level - 1);//缩进距离
QRect r = rect;
r.setLeft(r.left() + indentaions);//图标绘制位置
painter->save();
painter->setPen(m_branchLine);
bool expaned = isExpanded(index);//节点是否展开
QLine line(r.center() + QPoint(0, r.top() - r.center().y()), r.center() + QPoint(0, r.bottom() - r.center().y()));
line.translate(-indentaion, 0);
//QLine line(r.topLeft(), r.bottomLeft());
//循环绘制(具有兄弟节点的)父节点向下的竖线
DataNode * parent_node = node->parent();
DataNode * sub_node = node;
bool isNeed = node->children().size() == 0;
for (int i = level - 1; i >= 0; --i)
{
QList<DataNode *> & children = parent_node->children();
bool has_next_siblings = children.indexOf(sub_node) != (children.size() - 1);//父节点是否有(向后的)兄弟
if (has_next_siblings)
{
painter->drawLine(line);
}
if (level - 1 == i)
{
QPoint pos = (line.p1() + line.p2()) / 2;
QPoint pos2 = pos + QPoint(indentaion / 2, 0);
painter->drawLine(pos, pos2);
if (!has_next_siblings)
{
painter->drawLine(line.p1(), (line.p1() + line.p2()) / 2);
}
}
sub_node = parent_node;
parent_node = parent_node->parent();
line.translate(-indentaion, 0);
}
QPixmap pix;
if (expaned)
{
if (hasChild)
{
pix = QPixmap(":/branch-expand.png");
}
}
else
{
if (hasChild)
{
pix = QPixmap(":/branch-collapse.png");
}
}
if (pix.isNull() == false)
{
QRect pixRect = QRect(QPoint(0, 0), pix.size());
pixRect.moveCenter(r.center());
if (expaned)
{
QLine line(r.center(), r.center() + QPoint(0, r.bottom() - r.center().y()));
painter->drawLine(line);
}
painter->drawPixmap(pixRect, pix);
}
painter->restore();
}
3、同步左侧表头
上一篇文章Qt实现表格树控件-支持多级表头 中已经说了,我们的表格控件是使用QTableView+QTreeView来实现的,那么我们操作树控件时必然要对表格中的表头进行同步操作了。
树控件折叠时隐藏垂直表头指定行
void collapsed_p(DataNode * node)
{
QList<DataNode *> childNodeList = node->children();
//DataManager::getInstance()->allChildNode(node, childNodeList);
int size = childNodeList.size();
for (int i = 0; i < size; ++i)
{
int serial = DataManager::getInstance()->serialNoOfNode(childNodeList.at(i));
VHeaderView::instance->SetRowHide(serial, true);
QModelIndex subIndex = FrozenTreeView::instance->rowIndex(serial);
collapsed_p(childNodeList.at(i));
}
}
void FrozenTreeView::onCollapsed(const QModelIndex & index)
{
if (!index.isValid())
return;
DataNode * node = static_cast<DataNode*>(index.internalPointer());
if (nullptr == node)
return;
collapsed_p(node);
VHeaderView::instance->UpdateCache();
//要对水平头的最后一列进行重设大小,引起水平头自己的更新操作,从而使整个界面显示正确
HHeaderView::instance->resizeLastSection(true);
}
树控件展开时显示垂直表