QML树控件TreeView默认展开所有节点的方法和实现

QML树控件TreeView默认展开所有节点的方法和实现

2023年6月22日发(作者:)

QML树控件TreeView默认展开所有节点的⽅法和实现背景 近来在做Qt界⾯设计相关的项⽬,由于主窗体的框架是⽤QtQuick搭建的,所以必须从传统的C++开发转向JS风格的QML开发,QML我理解他的话就是⼀个JavaScript风格的描述性说明语⾔,⾄于QtQuick则相当于Qt官⽅为qml开发提供的⼀个通⽤强⼤的组件库吧,QML与QtQuick的关系相当于C++与STL吧。扯远了,说⽩了就是在项⽬的开发过程中,需要构建⼀个提供导航功能的流程树,其所有节点默认是展开的,点击打开其⼦节点对应的界⾯。 树控件TreeView是在Qt5.5版本以后才有的,其功能也⼗分强⼤,可直接代替之前ListView等控件对于树结构的不灵活构建,可使⽤MVC数据与视图分离的⽅式灵活配置树结构和数据。 当使⽤MVC的⽅式构建好树节点的数据,并写好qml的布局之后,运⾏发现默认情况下树只显⽰根节点下的所有⽗节点,需要点击三⾓符号才会展开,或者实现以下代码,通过单击或双击⽗节点展开⼦项,但也需要⼀项⼀项的展开,如下代码:property bool isExpand: trueonClicked: { if(isExpand) { emit: (index); isExpand = false; } else { emit: se(index); isExpand = true; }} 问题 不像QTreeView,它有expandAll()的⽅法,可在加载界⾯和数据后直接展开全部节点。qml的TreeView控件的帮助⽂档中只提供了单个节点的展开和收缩⽅法如下代码:// 参数为单个节点的indexvoid collapse(QModelIndex index);//Collapses the model item specified by the index.//See also collapsed and expand(QModelIndex index);//Expands the model item specified by the index.//See also expanded and isExpanded. 并且在⽹上找了各种⽂章,也没发现Qt提供了展开所有包含⼦项的树节点,甚⾄在⼀些贴吧⾥还发现了提出此问题的同⾏,⾄今没发现解决办法。由于项⽬的需求,这个问题是我必须迈过的坎,通过⼤概⼀周的尝试和写demo,最终以⾃⼰的⽅式解决,虽然此⽅法看起来不是很聪明的样⼦,但是也完全解决了此问题,希望能给遇到此问题的同⾏提供⼀些思路。思路 我们再来拆解下问题,项⽬加载TreeView时实现默认(⾃动)展开所有节点(包含⼦项的节点),⽽qml TreeView中只提供了展开单个树节点的⽅法,那么这问题可转化为,找到树上所有包含⼦项的节点的QModelIndex然后依次调⽤void expand(QModelIndex index);⽅法即可。此时的难点就变成了遍历此树,找出包含⼦项的节点的index。 由于TreeView采⽤了MVC的⽅式构建,树的数据是在C++中的TreeModel类中实现的,因此解决此问题必须的使⽤qml和c++混合编程,这时我们的思路就是:项⽬加载完qml的view和model后,qml调⽤c++的TreeModel类的⽅法,此⽅法中遍历树数据结构,找到包含⼦项的节点,则发射TreeModel定义的信号,信号中包含此节点的QModelIndex,qml的tree控件响应此信号,调⽤展开⽅法。遍历结束,则全部节点展开完成。流程图如下图: 实现了,转了⼀个圈(qml --> c++ --> qml)啊,是不是有点笨。实现 此篇⽂章是在读者已经掌握了实现MCV框架的qml TreeView控件的所有知识的基础上阅读的,如果对qml和qml TreeView不熟,建议先恶补⼀下基础知识,此处推荐⼀个⼤佬的博客链接,也是我学习qml从头看完的帖⼦,⾮常棒,,其中⼀篇讲qml和C++混合编程的建议反复观看,。 插⼀句,Qt⾃带的帮助⽂档真的特别特别⽅便和全⾯,建议从事Qt开发的同⾏,时时刻刻都应该打开帮助。 对MCV实现不熟的,⽹上多找找,例⼦⾮常多,当然Qt欢迎界⾯的实例中就有完整的⽰例,推荐⼀篇⽂章吧,。 扯远了扯远了,我们赶快进⼊正题吧!1. TreeView加载完毕调⽤C++ TreeModel类的槽函数 采⽤qml的⽅法如下代码:import QtQuick 2.12import 2.12import 2.2 // 使⽤TreeViewimport del 1.0 // 注册到元对象中的C++类Window { // 属性 略 TreeModel { id: treeModel; // C++类 } TreeView {

// 略 }

// qml加载完毕 默认执⾏此段 leted: { TreeExpand(); // C++槽函数 }}2. C++ TreeModel类槽函数handleTreeExpand的实现 TreeModel的槽函数handleTreeExpand主要实现,遍历树的所以节点,找出包含⼦项的节点,发射TreeModel中定义的信号voidexpandTreeNode(QModelIndex index); 这部分的代码如下:TreeModel.h#include #include #include #include "TreeItem.h" // ⽤来保存树节点的数据结构类,不明⽩请参考MVC的实现class TreeItem;class TreeModel : public QAbstractItemModel{ Q_OBJECTpublic:

// ...signals: // 发射展开信号和要展开的节点index void expandTreeNode(QModelIndex index);public:

// C++处理展开槽函数 遍历树结构 找到需展开的节点 void handleTreeExpand();private: // 处理⽗节点下的⼦节点 递归 知道没有⼦节点返回 void handleChildItemExpand(TreeItem* parent); TreeItem* m_rootItem; // 保存树结构的根节点}#include "TreeModel.h"// ...

// 槽函数实现void TreeModel::handleTreeExpand(){ // 根节点下⼀级⼦节点的个数 int count = m_rootItem->childCount();

for(int i = 0; i < count; ++i) { // 依次遍历⼀级⼦节点

auto childItem = m_rootItem->child(i); for(0 < chileItem->childCount()) { // 包含⼦项的节点 展开 emit expandTreeNode(createIndex(i, 0, childItem));

// 处理 此⼀级节点的⼦节点 handleChildItemExpand(childItem); } }}void TreeModel::handleChildItemExpand(){ int count = parent->childCount(); for(int i = 0; i < count; ++i) { for(0 < chileItem->childCount()) { // 包含⼦项的节点 展开 emit expandTreeNode(createIndex(i, 0, childItem));

// 递归处理 此级节点的⼦节点 handleChildItemExpand(childItem); } }}3. qml中连接C++的信号expandTreeNode实现节点展开 直接上代码实现吧import QtQuick 2.12import 2.12import 2.2 // 使⽤TreeViewimport del 1.0 // 注册到元对象中的C++类Window { // 属性 略 MyTreeModel { id: treeModel; // C++类 } TreeView { id: myTree;

// 略 }

// qml加载完毕 默认执⾏此段 leted: { TreeExpand(); // C++槽函数 }

// 连接C++中定义的信号 Connections { target: treeModel; onExpandTreeNode: { // 注意qml中对于信号的写法 emit: (index); } }} 看到这⾥,肯定会有童鞋问了:怎样把C++类注册到qml元对象中?qml中可以访问C++类的哪些属性?害,知识就在那,学不学看你。写在最后 如果我说这个问题的思路,⽅法和实现已经全部讲完,可能某些童鞋会⼀脸懵吧,甚⾄会说:这算什么⽂章嘛? 代码断断续续,这省那略的,完全看不懂;全篇⼀个实现效果图都没有,运⾏结果也没有,确定解决了吗?只看到了啰⾥啰唆的废话了。 这是我写完后看了这篇⽂章的感受,代替⼀些童鞋说了出来,如果有同感的,欢迎点评。 还是得解释⼀下滴,这个问题是我在公司项⽬中遇到的,测试代码和demo都是在内⽹⼯作机上实现的,并且项⽬这部分⼯作提交了后,我才有功夫写这篇⽂章的,所以这个⽅法是完全能解决这个问题的。当然还是得在QML与C++混合编程,并且采⽤了MCV的框架的背景下才⾏。如果有实现⽅⾯的问题欢迎随时评论交流。 ⼯作以来的第⼀篇⽂章,真是懒啊⾃⼰! 欢迎各位⼤佬交流指正!

发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1687383110a5959.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信