Qt 模型视图 - QTreeWidget(3)

1 简述

  • 在实际开发中可能会用到类似树型控件的需求,在Qt中QTreeWidget是一个方便的类,它提供了一个标准的树形小部件,带有一个经典的基于项目的接口。这个类基于Qt的模型/视图架构,并使用一个默认模型来保存项目,每个项目都是一个QTreeWidgetItem。
  • 本节模仿WPS导航窗格中书签的界面,用QTreeWidget实现其大概的界面。

开发环境

  • 系统:Window10
  • Qt版本:5.14.2
  • 编译器:MinGW_64

2 实现效果

在这里插入图片描述 在这里插入图片描述

3 实现步骤

  1. 初始化QTreeWidget数据
ui->treeWidget->setHeaderHidden(true);
ui->treeWidget->setColumnCount(1);
ui->treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
ui->treeWidget->setDragEnabled(true);
ui->treeWidget->setDragDropMode(QAbstractItemView::InternalMove);
ui->treeWidget->setEditTriggers(QAbstractItemView::DoubleClicked);
ui->treeWidget->viewport()->setAcceptDrops(true);
ui->treeWidget->setDropIndicatorShown(true);
ui->treeWidget->setFocusPolicy(Qt::NoFocus);

QFile file(":/res/style.qss");
if (file.open(QFile::ReadOnly)) {
    QString qss = file.readAll();
    this->setStyleSheet(qss);
    file.close();
}
  1. 读取文件数据并将每行数据添加到QTreeWidget
void Widget::initTreeData()
{
    QFile file(":/res/bookmark.txt");
    if (!file.open(QFile::ReadOnly)) {
        qInfo() << "文件打开失败!";
        return;
    }
    QString line;
    QStringList rowList;
    while (!file.atEnd()) {
        line = file.readLine();
        rowList.append(line);
    }
    initContentsOfTreeRow(rowList);
    file.close();
    // 记录前一个项
    previousParentNode = nullptr;
}

// 处理每行数据
void Widget::initContentsOfTreeRow(const QStringList &rowListContent)
{
    int rowCount = rowListContent.size();
    for (int i = 0; i < rowCount; ++i) {
        QString rowContent = rowListContent.at(i).trimmed();
        if (rowContent.startsWith("--")) { // 是子结点
            QTreeWidgetItem *childItem = new QTreeWidgetItem(previousParentNode);
            childItem->setIcon(0, QIcon(":/res/bookmark.png"));
            childItem->setText(0, rowContent.mid(2));
            childItem->setSizeHint(0, QSize(childItem->sizeHint(0).width(), 35));
            childItem->setFlags(childItem->flags() | Qt::ItemIsEditable);
        } else { // 顶层结点
            QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
            item->setIcon(0, QIcon(":/res/bookmark.png"));
            item->setText(0, rowContent);
            item->setSizeHint(0, QSize(item->sizeHint(0).width(), 35));
            item->setFlags(item->flags() | Qt::ItemIsEditable);
            previousParentNode = item;
        }
    }
}
  1. bookmark.txt数据
致谢|5
介绍|6
前言|9
关于本书|11
关于作者|13
关于封面|141章 你好,C++的并发世界|15
--1.1 何谓并发|16
--1.2 为什么使用并发?|20
--1.3 C++中的并发和多线程|22
--1.4 开始入门|24
--1.5 本章总结|262章 线程管理|27
--2.1 线程管理的基础|28
--2.2 向线程函数传递参数|34
--2.3 转移线程所有权|37
--2.4 运行时决定线程数量|41
--2.5 标识线程|44
--2.6 本章总结|453章 线程间共享数据|46
--3.1 共享数据带来的问题|47
--3.2 使用互斥量保护共享数据|50
  1. 添加项和删除项
	// ----------添加项----------
	QTreeWidgetItem * curItem = nullptr;
	if (ui->treeWidget->topLevelItemCount() != 0) { // 有顶层项
	    curItem = ui->treeWidget->currentItem(); // 获取当前项
	}
	if (curItem != nullptr) {
	    QTreeWidgetItem *parentItem = curItem->parent();
	    QTreeWidgetItem *item = nullptr;
	    if (parentItem == nullptr) { // 没有父节点
	        item = new QTreeWidgetItem();
	        item->setIcon(0, QIcon(":/res/bookmark.png"));
	        item->setText(0, "【书签】新建书签");
	        item->setSizeHint(0, QSize(item->sizeHint(0).width(), 35));
	        item->setFlags(item->flags() | Qt::ItemIsEditable);
	        int index = ui->treeWidget->indexOfTopLevelItem(curItem); // 在顶层列表中的索引
	        ui->treeWidget->insertTopLevelItem(index + 1, item);
	    } else { // 有父节点
	        item = new QTreeWidgetItem();
	        item->setIcon(0, QIcon(":/res/bookmark.png"));
	        item->setText(0, "【书签】新建书签");
	        item->setSizeHint(0, QSize(item->sizeHint(0).width(), 35));
	        item->setFlags(item->flags() | Qt::ItemIsEditable);
	        int index = parentItem->indexOfChild(curItem); // 子元素列表中子元素的索引
	        parentItem->insertChild(index + 1, item);
	    }
	    // 添加完后需将此项设置为当前项
	    ui->treeWidget->setCurrentItem(item);
	    ui->treeWidget->editItem(item);
	} else { // 当前没有项
	    QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
	    item->setIcon(0, QIcon(":/res/bookmark.png"));
	    item->setText(0, "【书签】新建书签");
	    item->setSizeHint(0, QSize(item->sizeHint(0).width(), 35));
	    item->setFlags(item->flags() | Qt::ItemIsEditable);
	}
//*****************************************************************************
	// ----------添删除项----------
	QTreeWidgetItem * curItem = nullptr;
	if (ui->treeWidget->topLevelItemCount() != 0) { // 有顶层项
	    curItem = ui->treeWidget->currentItem();
	}
	if (curItem != nullptr) {
	    if (curItem->childCount() > 0) { // 有子项
	        QMessageBox::StandardButton btn = QMessageBox::information(this, "提示", "删除该书签将会删除其子书签,是否确定删除?",
	                                                                   QMessageBox::Ok | QMessageBox::Cancel,
	                                                                   QMessageBox::Ok);
	        if (btn == QMessageBox::Cancel) {
	            return;
	        }
	    }
	    QTreeWidgetItem *parentItem = curItem->parent();
	    if (parentItem == nullptr) { // 无父项
	        int index = ui->treeWidget->indexOfTopLevelItem(curItem);
	        delete ui->treeWidget->takeTopLevelItem(index);
	    } else { // 有父项
	        parentItem->removeChild(curItem);
	        delete curItem;
	    }
	} else { // 当前没有项
	    QMessageBox::information(this, "提示", "当前无书签!");
	}

4 总结

  1. 显示层级数据方便
  2. 可以添加复选框
  3. 支持自定义列表项:可根据自己的需求来
  4. 易于使用
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值