【Qt笔记】QTreeWidget控件详解

冷眼看人间恩怨 2024-09-18 08:35:01 阅读 82

 

目录

引言 

一、QTreeWidget的基本属性

1.1 列和表头

1.2 节点(QTreeWidgetItem)

1.3 展开和折叠

1.4 排序

1.5 选择模式

二、QTreeWidget的基本使用

2.1 创建QTreeWidget控件

2.2 设置大小和位置

2.3 设置列数和列标题

2.4 添加节点

2.5 读取节点

三、QTreeWidget的功能接口

3.1 条目操作

3.2 节点自定义

3.3 信号与槽机制

四、QTreeWidget 控件的进阶用法

4.1 自定义节点图标

4.2 节点展开与折叠

4.3 节点选择与交互

4.4 拖放支持

4.5 与模型/视图架构结合

五、应用示例 

5.1 代码 

5.2 实现效果

注意

结语 


引言 

QTreeWidget 是 Qt 框架中用于展示层次化数据的一个非常强大的控件,它继承自 QAbstractItemView 和 QTreeView,但提供了更为简便的接口来管理树形结构的数据。QTreeWidget 通常用于显示和操作具有父子关系的数据,如文件系统浏览器、组织结构图等。 

一、QTreeWidget的基本属性

1.1 列和表头

QTreeWidget支持多列显示,但通常第一列用于显示节点文本,其他列用于显示附加信息。可以通过 setHeaderLabels(QStringList labels) 方法设置表头标签。

1.2 节点(QTreeWidgetItem)

QTreeWidgetItem 是 QTreeWidget 中用于表示单个节点的类。每个 QTreeWidgetItem可以包含多个文本项(对应于列),并且可以有任意数量的子节点。

1.3 展开和折叠

用户可以通过点击节点旁的加号或减号来展开或折叠节点。也可以通过编程方式使用expandItem<code>(QTreeWidgetItem*item) 和 collapseItem(QTreeWidgetItem *item) 方法来控制节点的展开和折叠。

1.4 排序

QTreeWidget支持对列进行排序,通过点击列头可以实现。可以通过sortItems(int column, Qt::SortOrder order)方法进行编程排序。

1.5 选择模式

QTreeWidget支持多种选择模式,如单选、多选、扩展选择等,通过setSelectionMode(QAbstractItemView::SelectionMode mode)方法设置。

二、QTreeWidget的基本使用

2.1 创建QTreeWidget控件

在使用QTreeWidget控件之前,首先需要在代码中创建其实例。可以通过以下方式创建:

QTreeWidget *treeWidget = new QTreeWidget(parent);

其中,parent是QTreeWidget控件的父控件指针,可以为nullptr表示无父控件。 

2.2 设置大小和位置

QTreeWidget控件的大小和位置可以通过QWidget的resize()和move()函数来设置。例如:

treeWidget->resize(400, 300); // 设置控件大小为400x300

treeWidget->move(100, 100); // 设置控件在窗口中的位置为(100, 100)

2.3 设置列数和列标题

QTreeWidget支持多列显示,可以通过setColumnCount()函数设置列数,并通过setHeaderLabels()函数设置列标题。例如:

treeWidget->setColumnCount(2); // 设置列数为2

treeWidget->setHeaderLabels(QStringList() << "Name" << "Value"); // 设置列标题

2.4 添加节点

在QTreeWidget中添加节点通常涉及到QTreeWidgetItem类。可以使用addTopLevelItem()函数添加顶层节点,使用addChild()函数为节点添加子节点。例如:

QTreeWidgetItem *rootItem = new QTreeWidgetItem(QStringList() << "Root");

treeWidget->addTopLevelItem(rootItem);

QTreeWidgetItem *childItem = new QTreeWidgetItem(QStringList() << "Child");

rootItem->addChild(childItem);

2.5 读取节点

可以通过topLevelItem()函数获取顶层节点,通过child()函数获取子节点。例如:

QTreeWidgetItem *topItem = treeWidget->topLevelItem(0); // 获取第一个顶层节点

QTreeWidgetItem *child = topItem->child(0); // 获取第一个顶层节点的第一个子节点

三、QTreeWidget的功能接口

3.1 条目操作

QTreeWidget提供了丰富的条目操作接口,包括添加、删除、查找和排序等功能。

添加条目:通过addTopLevelItem()、addChild()等函数添加条目。删除条目:可以使用takeTopLevelItem()、removeChild()等函数删除条目。查找条目:可以通过遍历或自定义查找算法来查找符合条件的条目。排序条目:可以使用sortItems()函数对条目进行排序。

3.2 节点自定义

QTreeWidget允许自定义节点的样式和布局,包括设置字体、颜色、图标等。

设置字体和颜色:可以通过setFont()和setForeground()等函数设置节点的字体和颜色。设置图标:可以通过setIcon()函数为节点设置图标。自定义样式:可以使用QItemDelegate或QStyle来进一步自定义节点的样式。

3.3 信号与槽机制

QTreeWidget支持信号和槽机制,可以方便地处理节点的操作事件,如点击、双击、选择等。

常见信号:itemClicked、itemDoubleClicked、itemChanged等。连接信号和槽:使用connect()函数将信号与槽函数连接起来,实现事件处理。

四、QTreeWidget 控件的进阶用法

除了上述基本用法外,QTreeWidget 还支持以下进阶功能:

4.1 自定义节点图标

可以为每个节点设置自定义图标,以增强界面的友好性和直观性。

topItem1->setIcon(0, QIcon(":/path/to/icon.png")); // 为顶级节点设置图标

4.2 节点展开与折叠

可以通过编程方式控制节点的展开和折叠状态。 

treeWidget.expandItem(topItem1); // 展开顶级节点

treeWidget.collapseItem(topItem2); // 折叠另一个顶级节点

4.3 节点选择与交互

QTreeWidget 提供了丰富的信号和槽机制,用于处理节点的选择和交互事件。

connect(&treeWidget, &QTreeWidget::itemClicked, this, &YourClass::onItemClicked);

void YourClass::onItemClicked(QTreeWidgetItem *item, int column)

{

// 处理节点点击事件

}

4.4 拖放支持

通过实现拖放相关的接口,可以使 QTreeWidget 支持节点之间的拖放操作,从而实现数据的灵活移动和重组。

4.5 与模型/视图架构结合

对于更复杂的数据结构和交互需求,可以将 QTreeWidget 与 QAbstractItemModel 一起使用,以实现更灵活的数据管理和视图更新。

五、应用示例 

以下是一个QTreeWidget 控件的高级示例代码,它包括了样式表的设置、自定义QStyledItemDelegate、添加和删除列表项、列表项的点击槽函数以及选中样式的变化。 

5.1 代码 

#include <QApplication>

#include <QMainWindow>

#include <QTreeWidget>

#include <QTreeWidgetItem>

#include <QStyledItemDelegate>

#include <QPainter>

#include <QMouseEvent>

#include <QDebug>

// 自定义委托,用于绘制树形控件中的节点

class CustomDelegate : public QStyledItemDelegate {

public:

CustomDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {

QStyleOptionViewItem opt = option;

initStyleOption(&opt, index);

// 自定义绘制逻辑

if (index.isValid() && index.column() == 0) {

// 更改背景色

if (opt.state & QStyle::State_Selected) {

opt.palette.setColor(QPalette::Highlight, QColor(100, 149, 237)); // 选中时的背景色

}

// 绘制背景

QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);

} else {

QStyledItemDelegate::paint(painter, option, index);

}

}

};

class MainWindow : public QMainWindow {

Q_OBJECT

public:

MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {

setupUi();

connectSignals();

}

private:

void setupUi() {

treeWidget = new QTreeWidget(this);

treeWidget->setColumnCount(2);

QStringList headers;

headers << "Name" << "Type";

treeWidget->setHeaderLabels(headers);

// 设置样式表

treeWidget->setStyleSheet(

"QTreeWidget { background-color: #f0f0f0; }"

"QTreeWidget::item:selected { background-color: #6495ed; color: white; }"

"QTreeWidget::item:hover { background-color: #add8e6; }"

);

// 设置自定义委托

CustomDelegate *delegate = new CustomDelegate(treeWidget);

treeWidget->setItemDelegate(delegate);

// 添加一些数据

QTreeWidgetItem *rootNode = new QTreeWidgetItem(treeWidget);

rootNode->setText(0, "Root Node");

rootNode->setText(1, "Root Type");

QTreeWidgetItem *child1 = new QTreeWidgetItem(rootNode);

child1->setText(0, "Child 1");

child1->setText(1, "Type A");

// ... 可以继续添加更多子节点

// 展开根节点

rootNode->setExpanded(true);

// 设置窗口中心部件

setCentralWidget(treeWidget);

}

void connectSignals() {

connect(treeWidget, &QTreeWidget::itemClicked, this, &MainWindow::onItemClicked);

connect(addTopLevelButton, &QPushButton::clicked, this, &MainWindow::addTopLevelItem);

connect(addSubItemButton, &QPushButton::clicked, this, &MainWindow::addSubItem);

connect(deleteButton, &QPushButton::clicked, this, &MainWindow::deleteSelectedItem);

}

void onItemClicked(QTreeWidgetItem *item, int column) {

qDebug() << "Clicked item:" << item->text(column) << "Column:" << column;

}

// 添加和删除项的方法可以根据需要实现

// 增加顶点节点

void addTopLevelItem() {

QString text = QInputDialog::getText(this, "增加顶点节点", "请输入文本(格式:x.../x...):");

if(text.isEmpty())

{

QMessageBox::warning(this, "警告", "请输入文本");

return ;

}

QStringList list = text.split("/");

if(list.size() != 2)

{

QMessageBox::warning(this, "警告", "文本格式错误");

return ;

}

QTreeWidgetItem *newItem = new QTreeWidgetItem(treeWidget);

newItem->setText(0, list.at(0));

newItem->setText(1, list.at(1));

}

//增加子节点

void addSubItem() {

QTreeWidgetItem *selectedItem = treeWidget->currentItem();

if (!selectedItem) {

QMessageBox::warning(this, "错误", "请选择要添加子节点的顶点节点");

return;

}

QString text = QInputDialog::getText(this, "增加子节点", "请输入文本(格式:x.../x...):");

if(text.isEmpty())

{

QMessageBox::warning(this, "警告", "请输入文本");

return ;

}

QStringList list = text.split("/");

if(list.size() != 2)

{

QMessageBox::warning(this, "警告", "文本格式错误");

return ;

}

QTreeWidgetItem *newItem = new QTreeWidgetItem(treeWidget);

newItem->setText(0, list.at(0));

newItem->setText(1, list.at(1));

}

//删除节点

void deleteSelectedItem() {

if (QTreeWidgetItem *selectedItem = treeWidget->currentItem()) {

delete selectedItem; // 注意:这实际上会从树中删除项,但可能不会立即释放内存

}

}

//用于管理树形控件

QTreeWidget *treeWidget;

//增加顶点节点按钮

QPushButton *addTopLevelButton;

//增加子节点按钮

QPushButton *addSubItemButton;

//删除节点按钮

QPushButton *deleteButton;

};

#include "main.moc"

int main(int argc, char *argv[]) {

QApplication app(argc, argv);

MainWindow window;

window.resize(400, 300);

window.show();

return app.exec();

}

5.2 实现效果

注意

样式表:在QTreeWidget的样式表中,我设置了背景色、选中时的背景色和鼠标悬停时的背景色。

自定义委托:CustomDelegate类重写了paint方法来改变节点的绘制方式。这里,我根据项是否被选中来改变背景色,并保留了默认的文本绘制逻辑。

点击槽函数:onItemClicked槽函数会在用户点击树中的任何项时被调用,并打印出被点击的项和列的信息。

添加和删除项:在这个示例中,关于添加和删除项的具体实现,我规定的了添加项时输入的文本格式,文本格式错误或未输入时会出现提示框

moc:在Qt中,如果你使用了信号和槽,并且你的类继承自QObject或其子类,你需要使用Qt的元对象编译器(moc)来处理你的类。在上面的示例中,我使用了"main.moc"作为moc生成的元数据的占位符,但在实际项目中,这通常是由构建系统自动处理的。如果你使用的是Qt Creator和qmake,那么你可以忽略这一点。

结语 

QTreeWidget 是 Qt 中一个非常强大的控件,它提供了丰富的接口来管理树形结构的数据。通过上述的介绍和代码示例,你应该已经对如何使用 QTreeWidget 有了基本的了解。在实际开发中,根据具体需求,你可能还需要探索 QTreeWidget 的更多高级特性和用法。

以上就是关于Qt中QTreeWidget控件的全部介绍,如有不足与缺陷之处,欢迎评论区留言!!!  

 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。