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();
}

 

posted @ 2024-04-30 15:08  [BORUTO]  阅读(128)  评论(0)    收藏  举报