记录QTreeView使用(item勾选,事件,过滤)
QTreeView: 用于显示树状结构数据,适用于树状结构数据的操作。
在开发过程中很多时候需要用到树形结构的视图。在Qt中通常有QTreewidget以及QTreeView两种选择,对于QTreewidget它已经内置了一个数据模型,并且提供了方便的API来操作和管理树形结构的数据。通常用于数据简单,数据项少,解耦程度要求低的场合。但是代码非常简单。使用QTreeView可以更灵活地处理不同类型的树形结构数据,并进行自定义样式、编辑等操作等。
QTreeView本身不存储数据,而是通过与数据模型(如QStandardItemModel、QFileSystemModel等)的结合来展示数据。你需要先创建一个数据模型,并将其设置给QTreeView。
例子:
关键代码
1.初始化树
void QTreeViewDemo::initTree()
{
model = new QStandardItemModel(ui.treeView);
//设置树形结构表头信息
model->setHorizontalHeaderLabels(QStringList() << QStringLiteral("文件名") << QStringLiteral("数据信息"));
//设置树形结构根节点信息
QStandardItem* itemProject = new QStandardItem(QIcon(":/QTreeViewDemo/Resources/folder.png"), QStringLiteral("电脑"));
//itemProject->setData("根节点", Qt::UserRole + 1); // 用户数据
model->appendRow(itemProject);
model->setItem(model->indexFromItem(itemProject).row(), 1, new QStandardItem(QStringLiteral("信息说明")));
QStandardItem* itemFolder = new QStandardItem(QIcon(":/QTreeViewDemo/Resources/folder.png"), QStringLiteral("文件夹1"));
itemProject->appendRow(itemFolder);
//itemFolder->setData("一级节点", Qt::UserRole + 1); // 用户数据
itemProject->setChild(itemFolder->index().row(), 1, new QStandardItem(QStringLiteral("信息说明")));
itemFolder = new QStandardItem(QIcon(":/QTreeViewDemo/Resources/folder.png"), QStringLiteral("文件夹2"));
itemProject->appendRow(itemFolder);
for (int i = 0; i < 5; ++i) {
QStandardItem* itemgroup = new QStandardItem(QIcon(":/QTreeViewDemo/Resources/folder.png"), QStringLiteral("Group%1").arg(i + 1));
itemFolder->appendRow(itemgroup);
for (int j = 0; j < (i + 1); ++j) {
QStandardItem* itemchannel = new QStandardItem(QIcon(":/QTreeViewDemo/Resources/folder.png"), QStringLiteral("文件%1").arg(j + 1));
itemgroup->appendRow(itemchannel);
itemgroup->setChild(itemchannel->index().row(), 1, new QStandardItem(QStringLiteral("文件%1信息说明").arg(j + 1)));
}
}
itemProject->setChild(itemFolder->index().row(), 1, new QStandardItem(QStringLiteral("文件夹2信息说明")));
itemProject = new QStandardItem(QIcon(":/QTreeViewDemo/Resources/folder.png"), QStringLiteral("手机"));
itemProject->setCheckable(true);//设置有勾选框
itemProject->setTristate(true);//
model->appendRow(itemProject);
for (int i = 0; i < 3; ++i)
{
itemFolder = new QStandardItem(QIcon(":/QTreeViewDemo/Resources/folder.png"), QStringLiteral("文件夹%1").arg(i + 1));
itemFolder->setCheckable(true);
itemFolder->setTristate(true);
QStandardItem* itemFolderDes = new QStandardItem(QIcon(":/QTreeViewDemo/Resources/folder.png"), QStringLiteral("Group%1").arg(i + 1));
itemProject->appendRow(itemFolder);
itemProject->setChild(itemFolder->index().row(), 1, itemFolderDes);
for (int j = 0; j < i + 1; ++j)
{
QStandardItem* item = new QStandardItem(QIcon(":/QTreeViewDemo/Resources/folder.png"), QStringLiteral("文件%1").arg(j + 1));
item->setCheckable(true);
itemFolder->appendRow(item);
itemFolder->setChild(item->index().row(), 1, new QStandardItem(QStringLiteral("文件%1信息说明").arg(j + 1)));
}
}
//关联项目属性改变的信号和槽
connect(model, &QStandardItemModel::itemChanged, this, &QTreeViewDemo::treeItemChanged);
ui.treeView->setModel(model);
ui.treeView->setColumnWidth(0,150);
ui.treeView->expandAll();
ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui.treeView, &QTreeView::customContextMenuRequested, this, &QTreeViewDemo::onTreeViewMenuRequested);
}
2.单击item事件
void QTreeViewDemo::on_treeView_clicked(const QModelIndex &index)
{
//QStandardItem* item = mModel->itemFromIndex(index);
ui.textEdit->append("Clicked "+ index.data().toString());
QString str;
str += QStringLiteral("当前选中:%1\nrow:%2,column:%3\n").arg(index.data().toString())
.arg(index.row()).arg(index.column());
str += QStringLiteral("父级:%1\n").arg(index.parent().data().toString());
//兄弟节点测试
QString name, info;
if (index.column() == 0)
{
name = index.data().toString();
info = index.sibling(index.row(), 1).data().toString();
}
else
{
name = index.sibling(index.row(), 0).data().toString();
info = index.data().toString();
}
str += QStringLiteral("名称:%1\n信息:%2\n").arg(name).arg(info);
//寻找顶层
QString top = getTopParent(index).data().toString();
str += QStringLiteral("顶层节点名:%1\n").arg(top);
//当前节点item
QStandardItem *pItem = model->itemFromIndex(index);
if (pItem) {
QString s = pItem->data().toString();
QVariant variant = pItem->data(Qt::UserRole + 1); // 获取用户数据
Test user = variant.value<Test>();
str += QStringLiteral("当前节点数据信息:%1\n%2\n%3\n").arg(user.text1).arg(user.text2).arg(user.text3);
}
//ui->label_realTime->setText(str);
ui.plainTextEdit->setPlainText(str);
}
3.双击item事件
void QTreeViewDemo::on_treeView_doubleClicked(const QModelIndex & index)
{
ui.textEdit->append("doubleClicked " + index.data().toString());
}
4.节点添加图标以及勾选框
//添加图标
QStandardItem* itemProject = new QStandardItem(QIcon(":/QTreeViewDemo/Resources/folder.png"), QStringLiteral("电脑"));
//添加勾选框
itemProject->setCheckable(true);
5.节点勾选事件触发
(1)Item全部选中
void QTreeViewDemo::treeItem_checkAllChild(QStandardItem * item, bool check)
{
if (item == nullptr)
return;
int rowCount = item->rowCount();
for (int i = 0; i < rowCount; ++i)
{
QStandardItem* childItems = item->child(i);
treeItem_checkAllChild_recursion(childItems, check);
}
if (item->isCheckable())
item->setCheckState(check ? Qt::Checked : Qt::Unchecked);
}
(2)item三种状态判断(半选,全选,不选)
void QTreeViewDemo::treeItem_CheckChildChanged(QStandardItem * item)
{
if (nullptr == item)
return;
Qt::CheckState siblingState = checkSibling(item);
QStandardItem * parentItem = item->parent();
if (nullptr == parentItem)
return;
if (Qt::PartiallyChecked == siblingState)
{
if (parentItem->isCheckable() && parentItem->isTristate())
parentItem->setCheckState(Qt::PartiallyChecked);
}
else if (Qt::Checked == siblingState)
{
if (parentItem->isCheckable())
parentItem->setCheckState(Qt::Checked);
}
else
{
if (parentItem->isCheckable())
parentItem->setCheckState(Qt::Unchecked);
}
treeItem_CheckChildChanged(parentItem);
}