You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何给QTreeView添加项?代码无显示及嵌入QPushButton问题排查

QTreeView仅显示边框无内容+嵌入按钮失败的问题分析

你的代码存在两个核心问题,直接导致了当前的异常现象:

1. 模型生命周期错误,TreeView失去数据来源

你在构造函数内声明了局部变量QStandardItemModel model,当构造函数执行完毕后,这个局部模型会被自动销毁,TreeView绑定的模型变成无效指针,自然无法显示任何内容。

解决办法:将模型改为堆分配(用new创建),或者把模型声明为MainWindow的成员变量,确保其生命周期和TreeView保持一致。

2. 直接存储按钮指针无法触发TreeView渲染控件

item1->setData(QVariant::fromValue(static_cast<void*>(button)))只是把按钮指针存在了item的自定义数据里,TreeView默认不会识别并渲染这个指针对应的控件。要在TreeView单元格中嵌入按钮,必须使用**自定义委托(QStyledItemDelegate)**来负责单元格的绘制和事件响应。


修改后的完整代码示例

#include <QMainWindow>
#include <QTreeView>
#include <QStandardItemModel>
#include <QGridLayout>
#include <QPushButton>
#include <QStyledItemDelegate>
#include <QMouseEvent>
#include <QDebug>

// 自定义委托,实现按钮渲染与点击响应
class ButtonDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit ButtonDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        // 仅在第一列绘制按钮
        if (index.column() != 0) {
            QStyledItemDelegate::paint(painter, option, index);
            return;
        }

        QPushButton button;
        button.setText(index.data(Qt::DisplayRole).toString());
        button.resize(option.rect.size());

        // 将按钮绘制到单元格区域
        painter->save();
        painter->translate(option.rect.topLeft());
        button.render(painter);
        painter->restore();
    }

    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        if (index.column() == 0) {
            QPushButton button;
            return button.sizeHint();
        }
        return QStyledItemDelegate::sizeHint(option, index);
    }

    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override
    {
        // 处理按钮点击事件
        if (index.column() == 0 && event->type() == QEvent::MouseButtonRelease) {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            if (option.rect.contains(mouseEvent->pos())) {
                emit buttonClicked(index.row());
            }
            return true;
        }
        return QStyledItemDelegate::editorEvent(event, model, option, index);
    }

signals:
    void buttonClicked(int row);
};

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

    QGridLayout* layout = new QGridLayout();
    ui.centralWidget->setLayout(layout);

    QTreeView* treeView = new QTreeView(this);
    treeView->setStyleSheet(R"(
        QTreeView {
            background-color: transparent;
        }
    )");

    // 改用堆分配模型,保证生命周期与TreeView一致
    QStandardItemModel* model = new QStandardItemModel(this);
    treeView->setModel(model);

    // 设置表头
    QStandardItem* column1 = new QStandardItem("Column 1");
    column1->setBackground(QBrush(Qt::red));
    model->setHorizontalHeaderItem(0, column1);
    model->setHorizontalHeaderItem(1, new QStandardItem("Column 2"));

    // 添加数据行
    for (int i = 0; i < 5; i++) {
        QList<QStandardItem*> row;
        QStandardItem* item1 = new QStandardItem("Button " + QString::number(i));
        QStandardItem* item2 = new QStandardItem("More data " + QString::number(i));
        row << item1 << item2;
        model->appendRow(row);
    }

    // 为TreeView设置自定义委托
    ButtonDelegate* delegate = new ButtonDelegate(this);
    treeView->setItemDelegate(delegate);
    // 连接按钮点击信号,可自定义处理逻辑
    connect(delegate, &ButtonDelegate::buttonClicked, [=](int row){
        qDebug() << "第" << row << "行的按钮被点击了!";
    });

    layout->addWidget(treeView);
}

#include "main.moc"

内容的提问来源于stack exchange,提问作者Cesar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:35:27