Qt|Qt之QTreeView的简单使用(含源码+注释)

一、QTreeView操作示例图 1.节点的添加删除示例图 下图为节点添加删除示例图,其中包含添加顶级节点、添加子节点、移除节点等操作;源码在本文第三节(源码含详细注释)。
Qt|Qt之QTreeView的简单使用(含源码+注释)
文章图片

2.节点的值的获取与修改 下图为节点对节点值的操作,其中包含获取值、设置值等;源码在本文第三节(源码含详细注释)。
Qt|Qt之QTreeView的简单使用(含源码+注释)
文章图片

二、QTreeView(个人理解) 这里我们将QTreeView和QTableView对比一下

  1. 二者都是类似MVC(Model View Controller)模式,其中都包含Delegate,请查看Qt代理的实现(按钮篇)、Qt代理的实现(常规控件篇);
  2. 二者都使用QStandardItemModel存放数据;
  3. QTreeView也存在一个继承其QTreeWidget的子类;
  4. QTreeView会唯一不同的是会操作item的子节点。
三、源码 CMainWindow.h
#ifndef CMAINWINDOW_H #define CMAINWINDOW_H#include #include //数据模型类namespace Ui { class CMainWindow; }class CMainWindow : public QMainWindow { Q_OBJECTpublic: explicit CMainWindow(QWidget *parent = 0); ~CMainWindow(); private slots:/** * @brief on_getCurNodeDataBtn_clicked 获取当前节点值 */ void on_getCurNodeDataBtn_clicked(); /** * @brief on_setCurNodeDataBtn_clicked 设置当前节点值 */ void on_setCurNodeDataBtn_clicked(); /** * @brief on_addTopNodeBtn_clicked 添加顶级节点 */ void on_addTopNodeBtn_clicked(); /** * @brief on_addChildNodeBtn_clicked 添加子节点 */ void on_addChildNodeBtn_clicked(); /** * @brief on_removeCurNodeBtn_clicked 移除当前节点 */ void on_removeCurNodeBtn_clicked(); private: Ui::CMainWindow*ui; QStandardItemModel*m_pModel; //数据模型对象指针 };

CMainWindow.cpp
#include "CMainWindow.h" #include "ui_CMainWindow.h"CMainWindow::CMainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::CMainWindow) { ui->setupUi(this); //设置窗口标题 this->setWindowTitle("QTreeView的简单使用"); //===============数据模型(QStandardItemModel)=============== //建立数据模型对象空间并指定父对象 m_pModel = new QStandardItemModel(ui->treeView); //将数据模型设置到树形视图上 ui->treeView->setModel(m_pModel); //设置水平表头列平均分 ui->treeView->header()->setSectionResizeMode(QHeaderView::Stretch); //添加列标题 m_pModel->setHorizontalHeaderLabels(QStringList() << "one" << "two"); }CMainWindow::~CMainWindow() { //! 析构函数: //! 有些小伙伴会发现我没有析构model、m_pFilterModel对象, //! 那是因为我在获取对象空间的时候指定了父对象, //! 当其父对象析构时,会先析构其子对象为指针的对象。 delete ui; }void CMainWindow::on_getCurNodeDataBtn_clicked() { //获取当前行列 QModelIndex curIndex = ui->treeView->currentIndex(); int row = curIndex.row(); int column = curIndex.column(); //当前位置包含-1值返回 if( -1 == row || -1 == column) { return; }///不获取item的情况/// /// 仅需要获取文本时使用 //! 通过index获取值,默认的data获取的是Qt::DisplayRole的值, //! 通常来说拿到的值就是显示的值 ui->valueEdit->setText(curIndex.data().toString()); }void CMainWindow::on_setCurNodeDataBtn_clicked() { //获取当前行列 QModelIndex curIndex = ui->treeView->currentIndex(); int row = curIndex.row(); int column = curIndex.column(); //当前位置包含-1值返回 if( -1 == row || -1 == column) { return; }///需要获取item的情况/// /// \brief curItem 当需要拿到具体item/位置时使用 /// 比如设置item值QStandardItem *curItem; int parentRow = curIndex.data(Qt::UserRole + 1).toInt(); //判断顶级节点值选择相应操作 if(-1 == parentRow) { curItem = m_pModel->item(row, column); } else { //获取当前位置的顶级节点 QStandardItem *parentItem = m_pModel->item(parentRow); //通过顶级节点获取子节点 curItem = parentItem->child(row, column); }//获取值编辑框中的值并设置到item上 curItem->setText(ui->valueEdit->text()); }void CMainWindow::on_addTopNodeBtn_clicked() { int index = m_pModel->rowCount(); QList topList; //链表容器添加顶级节点 topList << new QStandardItem(QString("顶级节点:%1-1").arg(index + 1)) << new QStandardItem(QString("顶级节点:%1-2").arg(index + 1)); //! 设置Qt::UserRole + n: 用户自定义值 //! 当n值不同时,相当于不同的键值,同理不同键则可设置不同值 //! 此处设置data是为了获取顶级节点值,通过该值判断和做出对应的操作 topList[0]->setData(-1, Qt::UserRole + 1); //设置父节点行,当值为-1时则当前为顶级节点 topList[1]->setData(-1, Qt::UserRole + 1); //添加顶级节点 m_pModel->appendRow(topList); }void CMainWindow::on_addChildNodeBtn_clicked() { //获取当前行列 QModelIndex curIndex = ui->treeView->currentIndex(); int row = curIndex.row(); int column = curIndex.column(); int parentRow = curIndex.data(Qt::UserRole + 1).toInt(); //当前行列值包含-1值或当前节点非顶级节点时返回 if( -1 == row || -1 == column || -1 != parentRow) { return; }//获取指定行的首个item QStandardItem *curTopItem = m_pModel->item(row); //为顶级节点添加子节点 QList childList; childList << new QStandardItem(QString("子节点:%1-1").arg(curTopItem->rowCount())) << new QStandardItem(QString("子节点:%1-2").arg(curTopItem->rowCount())); //设置item的data childList[0]->setData(row, Qt::UserRole + 1); childList[1]->setData(row, Qt::UserRole + 1); //添加子节点 curTopItem->appendRow(childList); }void CMainWindow::on_removeCurNodeBtn_clicked() { //获取当前行列 QModelIndex curIndex = ui->treeView->currentIndex(); int row = curIndex.row(); int column = curIndex.column(); //当前行列值包含-1值或当前节点非顶级节点时返回 if( -1 == row || -1 == column) { return; }int parentRow = curIndex.data(Qt::UserRole + 1).toInt(); //判断顶级节点值选择相应的移除操作 if(-1 == parentRow) { m_pModel->removeRow(row); } else { //移除某个子节点需要找到其顶级节点 QStandardItem *parentItem = m_pModel->item(parentRow); parentItem->removeRow(row); }}

四、拓展:上级节点的获取与判断 本文对于节点的判断是通过data设置用户定义值操作的,还有一种方法,是通过获取当前位置的QModelIndex对象获取其父对象的QModelIndex判断,代码如下(下方代码仅适用于本文):
提示:据说以下方法不严谨,如手动指定父类对象时。
void CMainWindow::parentIndex() { //获取当前节点的QModelIndex对象 QModelIndex index = ui->treeView->currentIndex(); //获取当前节点父对象的QModelIndex对象 QModelIndex parentIndex = index.parent(); //判断其父节点的行列值,顶级节点的父节点行列值为-1 if(-1 == parentIndex.row() || -1 == parentIndex.column()) { qDebug() << "当前节点为顶级节点"; } else { qDebug() << "当前节点为子节点"; }}

总结 【Qt|Qt之QTreeView的简单使用(含源码+注释)】QTreeView在判断节点位置时需要注意,并且要设置子节点需要线拿到其父节点才行;每个子节点只有通过其父节点行位置为0的item才可设置;QTreeView设置代理的方式和QTableView一样,需要注意的是,设置的列会贯穿子节点(子节点的对应列同样会生效)。
又是一周,明天继续搬砖了,加油!
相关文章 Qt之QTableView的简单使用(含源码+注释)
Qt代理的实现(按钮篇,含源码+注释)
Qt代理的实现(常规控件篇,含源码+注释)
Qt之QTableView设置多列表头复选框(自定义QHeaderView)、单元格复选框(含源码+注释)
Qt之QSortFilterProxyModel的简单使用(QTableView搜索功能,含源码+注释)
友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 ^o^/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除

    推荐阅读