Qt - QTreeWidget+QTreeWidgetItem 自定义控件
运行结果:

文件结构:

源码:
customtreewidget.h
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QWidget>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QSpinBox>
#include <QApplication>
#include <QDebug>
// 自定义条目控件Widget(将嵌入到TreeWidgetItem中)
class CustomItemWidget : public QWidget
{
Q_OBJECT
public:
explicit CustomItemWidget(QTreeWidgetItem *item, QWidget *parent = nullptr);
// 更新控件状态
void updateData(int value);
signals:
void updateClicked(QTreeWidgetItem *item, int value);
private:
QTreeWidgetItem *m_item;
QLabel *m_label;
QSpinBox *m_spinBox;
QPushButton *m_button;
};
customtreewidget.cpp
#include "customtreewidget.h"
CustomItemWidget::CustomItemWidget(QTreeWidgetItem *item, QWidget *parent): QWidget(parent), m_item(item)
{
// 控件布局
QHBoxLayout *layout = new QHBoxLayout(this);
layout->setContentsMargins(2, 2, 2, 2);
// 显示项名称
m_label = new QLabel("m_label", this);
// 数值调节控件
m_spinBox = new QSpinBox(this);
m_spinBox->setFixedSize(80,30);
m_spinBox->setRange(0, 100);
m_spinBox->setValue(50);
// 操作按钮
m_button = new QPushButton("Update", this);
layout->addWidget(m_label, 1);
layout->addWidget(m_spinBox, 2);
layout->addWidget(m_button, 1);
// 连接信号槽
connect(m_button, &QPushButton::clicked, [this](){
emit updateClicked(m_item, m_spinBox->value());
});
}
// 更新控件状态
void CustomItemWidget::updateData(int value)
{
m_spinBox->setValue(value);
m_label->setText(m_item->text(0));
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTreeWidget>
#include <QTreeWidgetItem>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void initTreeWidget();
private slots:
void handleUpdate(QTreeWidgetItem *item, int value);
private:
Ui::Widget *ui;
QTreeWidget *treeWidget; // 添加树控件成员变量
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include "customtreewidget.h"
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
initTreeWidget();
}
Widget::~Widget()
{
delete ui;
}
void Widget::initTreeWidget()
{
// 创建垂直布局
QVBoxLayout *layout = new QVBoxLayout(this);
// 创建树控件并设置基本属性
treeWidget = new QTreeWidget(this);
treeWidget->setColumnCount(2); // 必须设置列数
treeWidget->setHeaderLabels({"Item", "Value"}); // 设置列标题
// 创建根节点并添加到树控件
QTreeWidgetItem *root = new QTreeWidgetItem(treeWidget);
root->setText(0, "Root");
// 创建子节点
for(int i = 0; i < 3; ++i)
{
// 创建节点时必须指定父节点
QTreeWidgetItem *item = new QTreeWidgetItem(root);
item->setText(0, QString("Item %1").arg(i+1));
// 创建自定义控件
CustomItemWidget *customItem = new CustomItemWidget(item);
connect(customItem, &CustomItemWidget::updateClicked,this, &Widget::handleUpdate);
// 将控件绑定到第二列
treeWidget->setItemWidget(item, 1, customItem);
}
// 展开所有节点
treeWidget->expandAll();
// 将树控件添加到布局
layout->addWidget(treeWidget);
this->setLayout(layout); // 设置窗口主布局
}
void Widget::handleUpdate(QTreeWidgetItem *item, int value)
{
qDebug() << "Update item:" << item->text(0) << "value:" << value;
// 更新数据到item(存储到UserRole)
item->setData(1, Qt::UserRole, value);
// 正确调用方式:通过树控件实例访问 itemWidget()
if (auto widget = qobject_cast<CustomItemWidget*>(treeWidget->itemWidget(item, 1))) {
widget->updateData(value);
}
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}

浙公网安备 33010602011771号