《QTreeView中嵌入QPushButton实现命令操作》:系列教程之八(第8小节)

本小节属于《QTreeView使用代理实现表项编辑、定制显示控件》:系列教程之八的子章节。

由于本章节内容较多,放在一起可能大家看起来比较费劲,所以进行了拆分,大家可以从这里《QTreeView使用系列教程目录》找到其他的小节内容。


接下来开始讲解,QTreeView中嵌入QPushButton实现命令操作。

本小节比之前要稍微麻烦一些,之前我们都是嵌入的被动显示的控件,而QPushButton需要持久化存在。在显示的同时,还需要响应鼠标操作。但是跟双击启动一个Editor编辑数据不同,在同一时刻只会有一个Editor,QPushButton需要显示多个,持久化存在。

度娘到2个方案:

(1)重写paint()计算按钮位置,绘制按钮,然后重写editorEvent()处理鼠标消息,转化为按钮抬起信号。

参考《Qt 之模型/视图(自定义按钮)

(2)使用网友造好的一个轮子,大概原理也是通过重写paint()来实现的,但是我们派生出来使用时,与继承QStyledItemDelegate区别不大。

参考《Model/View模块中Delegate的扩展:持久Delegate(一)

这2个方案都能实现,具体怎么选择就看情况了。

下面以(2)方案为例进行说明:

PersistentStyledItemDelegate类为造好的轮子基类。我们派生出ButtonDelegate类。在createEditor()中,按照创建Editor并返回的思路,创建一个QWidget和QPushButton,然后把QPushButton布局在QWidget中,并返回QWidget,其间添加QPushButton信号通知出来,以便外部处理。

class ButtonDelegate : public PersistentStyledItemDelegate
{
    Q_OBJECT
public:
    ButtonDelegate(QObject *parent = nullptr)
        : PersistentStyledItemDelegate(parent) { }

    void setText(const QString &text) { _text = text; }
    void setIcon(const QIcon &icon) { _icon = icon; }

signals:
    void clicked(const QModelIndex& index);

public:
    //因为按钮既不需要从model读取数据,也不需要写入,因此仅需要重写一个函数即可
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QPersistentModelIndex perIndex(index);

        QWidget *widget = new QWidget(parent);
        widget->setAutoFillBackground(true);
        QHBoxLayout *layout = new QHBoxLayout();
        layout->addStretch();
        layout->setContentsMargins(2, 2, 2, 2);

        QPushButton *btn = new QPushButton();
        btn->setMinimumHeight(24);
        btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
        if (!_text.isEmpty())   btn->setText(_text);
        if (!_icon.isNull())   btn->setIcon(_icon);
        btn->setStyleSheet(BTN_QSS);
        layout->addWidget(btn);
        layout->addStretch();
        widget->setLayout(layout);

        QObject::connect(btn,&QPushButton::clicked,[=]{
            QModelIndex tIndex = static_cast<QModelIndex>(perIndex);
            //const成员里,不能修改对象,因此不能emit信号
            auto temp = const_cast<ButtonDelegate *>(this);
            emit temp->clicked(tIndex);
        });

        return widget;
    }

private:
    QString _text;
    QIcon _icon;
    const QString BTN_QSS = "QPushButton{"
                                "border-image: url(:/res/download_normal.png);"
                            "}"
                            "QPushButton::hover{"
                               "border-image: url(:/res/download_normal.png);"
                            "}"
                            "QPushButton::pressed{"
                                "border-image: url(:/res/download_press.png);"
                            "}";
};

给第7列指定委托,那么第7列使用QPushButton响应操作。

ButtonDelegate* button = new ButtonDelegate(ui->treeView);
connect(button, &ButtonDelegate::clicked, this, &MainWindow::onButtonClicked);
ui->treeView->setItemDelegateForColumn(7, button);
void MainWindow::onButtonClicked(const QModelIndex &index)
{
    if(!index.isValid())
            return;

    QMessageBox::information(this, "提示", QString("点击(%1,%2)").arg(index.row()).arg(index.column()));
}

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



若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

本文涉及工程代码,公众号回复:34EditorDelegate,即可下载。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

百里杨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值