Qt QTreeWidget项目知识点小结

前言

一个挺好玩的小Demo,里面所运用到知识点也是挺常用的。

运行效果:
在这里插入图片描述

在这里插入图片描述
其中包括功能:
右键菜单:右键鼠标弹出菜单项;
添加项:既可以添加父项,也可以添加子项;
删除项:将树表中的项进行删除;
生成随机数:生成随机数用于填充第二列;并计算出总数;
其他:设置正则表达式、添加图标、控件、右侧显示点击的项名称等。

ui界面

在这里插入图片描述

界面虽简单,程序精髓都在代码设计上。


撸代码

知识点汇总

VS qt支持显示中文
#pragma execution_character_set("utf-8") // qt支持显示中文

新建项
QTreeWidgetItem *schoolOne = new QTreeWidgetItem(ui.treeWidget); // 根项
QTreeWidgetItem *classOne = new QTreeWidgetItem(schoolOne); // 子项
注意:每个项都得设置父项

设置项的勾选状态
schoolOne->setCheckState(0, Qt::CheckState::Unchecked);
第一个参数指定设置第几列。

设置文本
schoolOne->setText(0, "小学");
第一个参数指定设置第几列。

设置工具提示
schoolOne->setToolTip(0, "小学");
第一个参数指定设置第几列。

设置图标
item->setIcon(0, QIcon("E:\\QTproject\\WPS\\images\\color.ico"));

设置树表头

QStringList headList;
headList << "School/Class" << "Class/Student Count" << "总分";
//ui.treeWidget->setHeaderLabel("School/Class");	// 设置一个
ui.treeWidget->setHeaderLabels(headList);	// 设置多个

隐藏下拉三角
ui.treeWidget->setRootIsDecorated(false);

隐藏表头
ui.treeWidget->setHeaderHidden(true);

设置选择模式
ui.treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
QAbstractItemView.SelectionMode.MultiSelection :多选(无需按ctrl)
QAbstractItemView.SelectionMode.ExtendedSelection :多选(按住ctrl,一次选一项)
QAbstractItemView.SelectionMode.ContiguousSelection :多选(一次选多项,相当于window下按住shift选文件)

设置列宽
ui.treeWidget->setColumnWidth(0, 170);
第一个参数指定设置第几列。

实例化菜单对象

this->m_menu = new QMenu;
this->m_addMenu = new QMenu("add");
this->m_addSchoolAction = new QAction("add School");
this->m_addClassAction = new QAction("add Closs");
this->m_delAction = new QAction("del");

this->m_addMenu->addAction(this->m_addSchoolAction);
this->m_addMenu->addAction(this->m_addClassAction);
	
this->m_menu->addMenu(this->m_addMenu);
this->m_menu->addAction(this->m_delAction);

// 为菜单项绑定槽函数
connect(this->m_addSchoolAction, SIGNAL(triggered()), this, SLOT(onAddSchool()));
connect(this->m_addClassAction, SIGNAL(triggered()), this, SLOT(onAddClass()));
connect(this->m_delAction, SIGNAL(triggered()), this, SLOT(onDelAction()));

得添加菜单右键事件

// 菜单右键事件
void contextMenuEvent(QContextMenuEvent *event);


// 右键菜单
void QTreeWidgets::contextMenuEvent(QContextMenuEvent *event) {
	// 菜单出现的位置为当前鼠标的位置
	this->m_menu->exec(QCursor::pos());
}

返回项的父项
item->parent()
无则返回NULL。
注意:根项是无父项的,只有子项才有父项。

显示一个输入框

bool ok = false;
QString schoolText = QInputDialog::getText(this, tr("添加学校"), tr("请输入学校名称:"), QLineEdit::Normal, "", &ok);

在这里插入图片描述

产生随机数
需添加头文件:#include <QTime>

QTime time;
time = QTime::currentTime();	// 获取当前系统时间(毫秒)
qsrand(time.msec() + time.second() * 1);	// 种下随机种子
int classPeople = qrand() % 100;    // 产生100以内的随机数  

返回tree小部件中的当前项
QTreeWidgetItem *item = ui.treeWidget->currentItem();

删除子项
itemParent->removeChild(item);
删除后记得释放item内存:delete item;

删除树中给定索引处的顶级项
ui.treeWidget->takeTopLevelItem(0);

返回给定顶级项的索引
ui.treeWidget->indexOfTopLevelItem(item);

获取所有顶级项的个数
int topLeveItemCount = ui.treeWidget->topLevelItemCount();

返回给定索引的顶级项
ui.treeWidget->topLevelItem(count);

获取项的第二列和第三列的文本

QTreeWidgetItem *ParentItem;
// 获取项的子项的个数
int count = ParentItem->childCount();
for (int i = 0; i < count; i++) {
	// 获得第二列和第三列的文本
	QString second = ParentItem->child(i)->text(1);
	QString third = ParentItem->child(i)->text(2);
}

使用正则表达式捕获字符串中的数字

// 正则表达式
QRegExp m_reg;
// 设置匹配模式
this->m_reg.setPattern("\\d*");	// 匹配任意多个数字

this->m_reg.indexIn("字符串");	// 根据正则表达式进行匹配
this->m_reg.cap(0).toInt();	// 捕获匹配到的数字

代码

有详细注释,对照着看应该可以看懂!

可将代码直接拷贝下来运行。
替换一下图标路径即可。

.h文件

#pragma once

#include <QtWidgets/QWidget>
#include "ui_QTreeWidgets.h"

#include <QMenu>
#include <QAction>
#include <QTreeWidgetItem>

class QTreeWidgets : public QWidget {
	Q_OBJECT

public:
	QTreeWidgets(QWidget *parent = Q_NULLPTR);

private:
	void initTreeWidgetItem();	// 初始化树列表
	void initQMenu();			// 初始化菜单

	// 菜单右键事件
	void contextMenuEvent(QContextMenuEvent *event);

	// 设置父项第二列与第三列的文本
	void setParentSecondAndThirdText(QTreeWidgetItem *ParentItem);

private slots:
	void onSetLabelText(QTreeWidgetItem *item, int column);	

	void onAddSchool();	// 添加学校(父项)
	void onAddClass();	// 添加班级(子项)
	void onDelAction();	// 删除项

	void on_determineBtn_clicked();	// 显示勾选上的父项信息

	void onDeleteChildAction(QTreeWidgetItem *item, int column);

private:
	Ui::QTreeWidgetsClass ui;

	// 菜单
	QMenu *m_menu;
	QMenu *m_addMenu;

	// 菜单子项
	QAction *m_addSchoolAction;
	QAction *m_addClassAction;

	QAction *m_delAction;


	// 正则表达式
	QRegExp m_reg;
};

.cpp文件

#include "QTreeWidgets.h"


#include <QDebug>
#include <QInputDialog>
#include <QMessageBox>
#include <QTime>
#include <QRegExp>
#include <QAbstractItemView>

#pragma execution_character_set("utf-8") // qt支持显示中文

QTreeWidgets::QTreeWidgets(QWidget *parent)
	: QWidget(parent) {
	ui.setupUi(this);

	// 设置匹配模式
	this->m_reg.setPattern("\\d*");	// 匹配任意多个数字

	ui.schoolNameLabel->setMinimumWidth(150);
	ui.classNameLabel->setMinimumWidth(150);

	initTreeWidgetItem();
	initQMenu();

	// 设置头文本
	QStringList headList;
	headList << "School/Class" << "Class/Student Count" << "总分";
	//ui.treeWidget->setHeaderLabel("School/Class");
	ui.treeWidget->setHeaderLabels(headList);

	// 隐藏下拉三角
	//ui.treeWidget->setRootIsDecorated(false);

	// 隐藏表头
	//ui.treeWidget->setHeaderHidden(true);


	//QAbstractItemView.SelectionMode.MultiSelection		:多选(无需按ctrl)
	//QAbstractItemView.SelectionMode.ExtendedSelection		:多选(按住ctrl,一次选一项)
	//QAbstractItemView.SelectionMode.ContiguousSelection	:多选(一次选多项,相当于window下按住shift选文件)
	// 设置选择模式
	ui.treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);

	// 设置列宽
	ui.treeWidget->setColumnWidth(0, 170);
	ui.treeWidget->setColumnWidth(1, 160);
	ui.treeWidget->setColumnWidth(2, 80);


	// 实现单击信号与槽的绑定
	connect(ui.treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(onSetLabelText(QTreeWidgetItem *, int)));
	// 实现双击信号与槽的绑定
	connect(ui.treeWidget, &QTreeWidget::itemDoubleClicked, this, &QTreeWidgets::onDeleteChildAction);
}


// 初始化项
void QTreeWidgets::initTreeWidgetItem() {

	{
		QTreeWidgetItem *schoolOne = new QTreeWidgetItem(ui.treeWidget);
		schoolOne->setCheckState(0, Qt::CheckState::Unchecked);
		schoolOne->setText(0, "小学");
		schoolOne->setToolTip(0, "小学");

		QTreeWidgetItem *classOne = new QTreeWidgetItem(schoolOne);
		classOne->setText(0, "小学一班");
		classOne->setText(1, "60人");
		classOne->setText(2, "3600分");
		classOne->setToolTip(0, "小学一班");

		QTreeWidgetItem *classTwo = new QTreeWidgetItem(schoolOne);
		classTwo->setText(0, "小学二班");
		classTwo->setText(1, "67人");
		classTwo->setText(2, "4020分");
		classTwo->setToolTip(0, "小学二班");

		QTreeWidgetItem *classThree = new QTreeWidgetItem(schoolOne);
		classThree->setText(0, "小学三班");
		classThree->setText(1, "59人");
		classThree->setText(2, "3540分");
		classThree->setToolTip(0, "小学三班");

	
		setParentSecondAndThirdText(schoolOne);
	}

	{
		QTreeWidgetItem *schoolTwo = new QTreeWidgetItem(ui.treeWidget);
		schoolTwo->setCheckState(0, Qt::CheckState::Unchecked);
		schoolTwo->setText(0, "初中");
		schoolTwo->setToolTip(0, "初中");

		QTreeWidgetItem *classOne = new QTreeWidgetItem(schoolTwo);
		classOne->setText(0, "初中一班");
		classOne->setText(1, "69人");
		classOne->setText(2, "1200分");
		classOne->setToolTip(0, "初中一班");

		QTreeWidgetItem *classTwo = new QTreeWidgetItem(schoolTwo);
		classTwo->setText(0, "初中二班");
		classTwo->setText(1, "86人");
		classTwo->setText(2, "3900分");
		classTwo->setToolTip(0, "初中二班");

		QTreeWidgetItem *classThree = new QTreeWidgetItem(schoolTwo);
		classThree->setText(0, "初中三班");
		classThree->setText(1, "76人");
		classThree->setText(2, "2400分");
		classThree->setToolTip(0, "初中三班");


		setParentSecondAndThirdText(schoolTwo);
	}

}

// 初始化菜单
void QTreeWidgets::initQMenu() {
	// 实例化菜单对象
	this->m_menu = new QMenu;
	this->m_addMenu = new QMenu("add");
	this->m_addSchoolAction = new QAction("add School");
	this->m_addClassAction = new QAction("add Closs");
	this->m_delAction = new QAction("del");


	this->m_addMenu->addAction(this->m_addSchoolAction);
	this->m_addMenu->addAction(this->m_addClassAction);
	
	this->m_menu->addMenu(this->m_addMenu);
	this->m_menu->addAction(this->m_delAction);


	connect(this->m_addSchoolAction, SIGNAL(triggered()), this, SLOT(onAddSchool()));
	connect(this->m_addClassAction, SIGNAL(triggered()), this, SLOT(onAddClass()));
	connect(this->m_delAction, SIGNAL(triggered()), this, SLOT(onDelAction()));

}

// 右键菜单
void QTreeWidgets::contextMenuEvent(QContextMenuEvent *event) {

	// 菜单出现的位置为当前鼠标的位置
	this->m_menu->exec(QCursor::pos());
}


// 设置Label
void QTreeWidgets::onSetLabelText(QTreeWidgetItem *item, int column) {
	// 点击的项有父亲
	if (item->parent() != NULL) {
		ui.schoolNameLabel->setText(item->parent()->text(column));
		ui.classNameLabel->setText(item->text(column));
	} else {
		ui.schoolNameLabel->setText(item->text(column));
		ui.classNameLabel->setText(item->text(column));
	}
}


// 添加学校
void QTreeWidgets::onAddSchool() {
	
	bool ok = false;
	QString schoolText = QInputDialog::getText(this, tr("添加学校"), tr("请输入学校名称:"), QLineEdit::Normal, "", &ok);

	if (ok && !schoolText.isEmpty()) {
		// 新建item设置父项为数表
		QTreeWidgetItem *item = new QTreeWidgetItem(ui.treeWidget);
		item->setCheckState(0, Qt::CheckState::Unchecked);
		item->setIcon(0, QIcon("E:\\QTproject\\WPS\\images\\color.ico"));
		item->setText(0, schoolText);
		item->setText(1, "0");
		item->setText(2, "0");

		// 设置工具提示
		item->setToolTip(0, schoolText);
	}
}


// 添加班级
void QTreeWidgets::onAddClass() {

	// 获取选中的一项
	QTreeWidgetItem *item = ui.treeWidget->currentItem();
	if (item == NULL) {
		QMessageBox::information(this, "提示", "请选择一项");
		return;
	}

	// 显示输入框
	bool ok = false;
	QString className = QInputDialog::getText(ui.treeWidget, tr("添加班级"), tr("请输入班级名称:"), QLineEdit::Normal, "", &ok);

	// 获取选中item的父项,如果父项是QTreeWidgetItem则返回该父项;如果父项是ui.treeWidget则返回NULL
	QTreeWidgetItem *itemParent = item->parent();

	// 选中的是子项
	if (itemParent != NULL) {
		QTime time;
		time = QTime::currentTime();	// 获取当前系统时间
		qsrand(time.msec() + time.second() * 1);	// 种下随机种子
		int classPeople = qrand() % 100;    // 产生100以内的随机数  

		QTreeWidgetItem *classItem = new QTreeWidgetItem(itemParent);
		//classItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsAutoTristate);
		classItem->setText(0, className);
		classItem->setIcon(0, QIcon("E:\\QTproject\\WPS\\images\\wps.ico"));
		classItem->setText(1, QString("%1人").arg(classPeople));
		classItem->setText(2, QString("%1分").arg(classPeople * 60));
		classItem->setToolTip(0, className);

		// 修改父项第二列与第三列的文本
		setParentSecondAndThirdText(itemParent);

	// 选中的是父项
	} else {
		// 方式一:
		/*QTreeWidgetItem *classItem = new QTreeWidgetItem(item);
		classItem->setText(column, className);
		classItem->setToolTip(column, className);*/

		QTime time;
		time = QTime::currentTime();	// 获取当前系统时间
		qsrand(time.msec() + time.second() * 1);	// 种下随机种子
		int classPeople = qrand() % 100;    // 产生100以内的随机数  

		// 方式二:
		QTreeWidgetItem *classItem = new QTreeWidgetItem;
		//classItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsAutoTristate);
		classItem->setText(0, className);
		classItem->setIcon(0, QIcon("E:\\QTproject\\WPS\\images\\wps.ico"));
		classItem->setText(1, QString("%1人").arg(classPeople));
		classItem->setText(2, QString("%1分").arg(classPeople * 60));
		classItem->setToolTip(0, className);
		// 父项添加子项
		item->addChild(classItem);

		setParentSecondAndThirdText(item);
	}
}


// 删除学校/班级
void QTreeWidgets::onDelAction() {
	// 返回tree小部件中的当前项。
	QTreeWidgetItem *item = ui.treeWidget->currentItem();
	if (item == NULL) return;

	QTreeWidgetItem *itemParent = item->parent();
	
	// 删除子项
	if (itemParent != NULL) {
		itemParent->removeChild(item);
		itemParent->setText(ui.treeWidget->currentColumn() + 1, QString("%1").arg(itemParent->childCount()));
		delete item;

		setParentSecondAndThirdText(itemParent);

	// 删除父项
	} else {
		// item->childCount() 返回子项的个数
		int count = item->childCount();
		for (int i = 0; i < count; i++) {
			item->removeChild(item->child(0));	// 删除子项
			delete item->child(0);	// 释放内存
		}
		
		// takeTopLevelItem:删除树中给定索引处的顶级项并返回它,否则返回0
		// indexOfTopLevelItem:返回给定顶级项的索引,如果找不到该项,则返回-1
		ui.treeWidget->takeTopLevelItem(ui.treeWidget->indexOfTopLevelItem(item));
		delete item;
	}
}


// 复选框打勾显示数据
void QTreeWidgets::on_determineBtn_clicked() {

	QString showMessage = "";

	// 获取所有顶级项的个数
	int topLeveItemCount = ui.treeWidget->topLevelItemCount();
	for (int count = 0; count < topLeveItemCount; count++) {
		// 遍历所有顶级项,复选框状态未选中则跳过循环
		if (ui.treeWidget->topLevelItem(count)->checkState(0) != Qt::CheckState::Checked) {
			continue;
		}
		// ui.treeWidget->topLevelItem(count) 获取inden对应的顶级项


		QString name, studentCount, score;
		// 存储顶级项所有列的数据
		name = ui.treeWidget->topLevelItem(count)->text(0);
		studentCount = ui.treeWidget->topLevelItem(count)->text(1);
		score = ui.treeWidget->topLevelItem(count)->text(2);

		showMessage += name + '\n' + studentCount + '\n' + score + '\n' + "---------------" + '\n';
	}

	QMessageBox::information(this, "提示", showMessage);


	for (int count = 0; count < topLeveItemCount; count++) {
		// 遍历所有顶级项,复选框状态选中则取消勾选
		if (ui.treeWidget->topLevelItem(count)->checkState(0) == Qt::CheckState::Checked) {
			// 取消勾选
			ui.treeWidget->topLevelItem(count)->setCheckState(0, Qt::CheckState::Unchecked);
		}	
	}

}


// 更新根项数据
void QTreeWidgets::setParentSecondAndThirdText(QTreeWidgetItem *ParentItem) {
	int classScore = 0;
	int score = 0;

	int count = ParentItem->childCount();
	for (int i = 0; i < count; i++) {
		// 获得第二列和第三列的文本
		QString second = ParentItem->child(i)->text(1);
		QString third = ParentItem->child(i)->text(2);

		// 计算学生总人数
		this->m_reg.indexIn(second);
		classScore += this->m_reg.cap(0).toInt();

		// 计算总分数
		this->m_reg.indexIn(third);	// 根据正则表达式进行匹配
		score += this->m_reg.cap(0).toInt();	// 捕获匹配到的数字
	}

	// 刷新父项的个数
	ParentItem->setText(1, QString("%1班 / %2人").arg(count).arg(classScore));
	// 刷新父项总分数
	ParentItem->setText(2, QString("%1分").arg(score));
}


// 双击删除子项
void QTreeWidgets::onDeleteChildAction(QTreeWidgetItem *item, int column) {
	if (item->parent() == NULL) return;

	QTreeWidgetItem *itemParent = item->parent();

	itemParent->removeChild(item);
	delete item;

	setParentSecondAndThirdText(itemParent);
}

总结:
此小项目使用到的知识点还是挺多的,不过也都是挺实用的,在其他类型的项目都可以用得到。

到此,MVC三个子类控件QLiseWidgetQTableWidget、QTreeWidget都已经记录完毕。

  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp_learners

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值