效果图
#include <QTreeWidget>
#include <QVBoxLayout>
#include <QStatusBar>
#include <QList>
class TreeView :public QTreeWidget
{
public:
TreeView(QWidget *pParent = nullptr) :QTreeWidget(pParent) {}
~TreeView() {};
};
class TreeFrame :public QFrame
{
Q_OBJECT
public:
TreeFrame(QWidget *pParent = nullptr);
~TreeFrame();
void initUI();
void initWidgetItem();
void connectSlots();
//改变选中状态时同步子节点
void syncChildNodeCheckState(QTreeWidgetItem *parentItem, Qt::CheckState state);
//改变选中状态时同步父节点
void syncParentNodeCheckState(QTreeWidgetItem *item);
protected slots:
//勾选节点的信号
void itemClicked(QTreeWidgetItem *pItem, int nCol);
private:
TreeView *m_pTreeView;
QTreeWidgetItem *m_pWidgetItem;
QStatusBar *m_pBar;
const static int m_STypeRole = Qt::UserRole;
//节点类型
enum NodeType
{
NT_RootNode = 0,
NT_ChildNode,
NT_ChildToChild
};
};
TreeFrame::TreeFrame(QWidget *pParent /*= nullptr*/) :QFrame(pParent)
{
initUI();
initWidgetItem();
connectSlots();
}
TreeFrame::~TreeFrame()
{
if (m_pTreeView)
{
delete m_pTreeView;
m_pTreeView = nullptr;
}
if (m_pWidgetItem)
{
delete m_pWidgetItem;
m_pWidgetItem = nullptr;
}
}
void TreeFrame::initUI()
{
this->setWindowTitle("Window Title");
m_pTreeView = new TreeView(this);
m_pTreeView->setHeaderHidden(true);
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->addWidget(m_pTreeView, 10000); //弹簧比例放大到10000倍
mainLayout->setSpacing(14);
QVBoxLayout* totalLayout = new QVBoxLayout();
totalLayout->setMargin(0);
totalLayout->setSpacing(0);
mainLayout->setContentsMargins(16, 16, 16, 6);
totalLayout->addLayout(mainLayout, 1);
m_pBar = new QStatusBar;
m_pBar->setFixedHeight(15);// 高度不能小于15个像素
m_pBar->setProperty("transparent", true);// 一定要设置属性
totalLayout->addWidget(m_pBar);
this->setLayout(totalLayout);
this->setMaximumHeight(200);
this->setMinimumWidth(100);
}
void TreeFrame::initWidgetItem()
{
m_pWidgetItem = new QTreeWidgetItem();
m_pWidgetItem->setText(0, "All Tree");
m_pWidgetItem->setCheckState(0, Qt::Unchecked);
m_pWidgetItem->setData(0, m_STypeRole, NT_RootNode);
m_pTreeView->addTopLevelItem(m_pWidgetItem);
//模拟数据,随便写的
for (int i = 0; i < 5; ++i)
{
QTreeWidgetItem *pItem = new QTreeWidgetItem();
pItem->setText(0, "ChildeOne");
pItem->setFlags(pItem->flags() | Qt::ItemIsUserCheckable);
pItem->setCheckState(0, Qt::Unchecked);
pItem->setData(0, m_STypeRole, NT_ChildNode);
m_pWidgetItem->addChild(pItem);
for (int j = 0; j < 5; ++j)
{
//节点下还有节点
QTreeWidgetItem *pItemChild = new QTreeWidgetItem();
pItemChild->setText(0, "ChildeTwo");
pItemChild->setFlags(pItemChild->flags() | Qt::ItemIsUserCheckable);
pItemChild->setCheckState(0, Qt::Unchecked);
pItemChild->setData(0, m_STypeRole, NT_ChildToChild);
pItem->addChild(pItemChild);
}
}
m_pTreeView->expandAll(); //展开所有节点
}
void TreeFrame::connectSlots()
{
connect(m_pTreeView, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(itemClicked(QTreeWidgetItem *, int)));
}
void TreeFrame::syncChildNodeCheckState(QTreeWidgetItem *parentItem, Qt::CheckState state)
{
if (parentItem != NULL && !parentItem->isHidden())
{
parentItem->setCheckState(0, state);
for (int i = 0; i < parentItem->childCount(); i++)
{
syncChildNodeCheckState(parentItem->child(i), state);
}
}
}
void TreeFrame::syncParentNodeCheckState(QTreeWidgetItem *item)
{
if (!item)
return;
QTreeWidgetItem *pParentItem = item->parent();
if (!pParentItem)
return;
int nCheckedNum = 0;
Qt::CheckState eState = Qt::Unchecked;
//遍历节点改变节点选中状态
for (int i = 0; i < pParentItem->childCount(); i++)
{
switch (pParentItem->child(i)->checkState(0))
{
case Qt::Checked:
eState = Qt::PartiallyChecked;
nCheckedNum++;
break;
case Qt::PartiallyChecked:
eState = Qt::PartiallyChecked;
break;
case Qt::Unchecked:
break;
default:
break;
}
}
if (nCheckedNum == pParentItem->childCount())
{
eState = Qt::Checked;
}
pParentItem->setCheckState(0, eState);
//同步一下节点状态
syncParentNodeCheckState(pParentItem);
}
void TreeFrame::itemClicked(QTreeWidgetItem *pItem, int nCol)
{
if (nCol != 0)
return;
Qt::CheckState eState = pItem->checkState(nCol);
//子节点同步选择状态
if (eState == Qt::Unchecked)
{
syncChildNodeCheckState(pItem, Qt::Unchecked);
}
else if (eState == Qt::Checked)
{
syncChildNodeCheckState(pItem, Qt::Checked);
}
//父节点同步
syncParentNodeCheckState(pItem);
}
#include "qtWidget.h"
#include <QtWidgets/QApplication>
#include "treeView.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TreeFrame Frame;
Frame.show();
return a.exec();
}