Qt QHeaderView自绘实现表头双击编辑,和添加按钮

在做数据展示时,为了偷懒少布局些界面元素,结果后面发现某部分功能无法很容易的实现,然后想到了Qt提供了控件自绘功能。具体实现效果为:表头的双击弹出输入框改变表头名称,点击按钮退出应用,也可以自定义为QMenu菜单等显示方式(注:之前想到用委托结果,设置好委托后一直没有效果,最后查看文档发现这么一句 Note: Each header renders the data for each section itself, and does not rely on a delegate. As a result, calling a header's setItemDelegate() function will have no effect。因此知道每个头显示每个节本身的数据,并且不依赖于委托)

效果图:

头文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPushButton>
#include <QHeaderView>

QT_BEGIN_NAMESPACE
class CustomHeaderView;
QT_END_NAMESPACE

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    CustomHeaderView *m_pHeader;
};

class CustomHeaderView : public QHeaderView     //自定义Header
{
    Q_OBJECT

public:
    explicit CustomHeaderView(Qt::Orientation orientation, QWidget *parent = nullptr);
    ~CustomHeaderView() Q_DECL_OVERRIDE;

signals:
    void Sig_ButtonClicked();
    void Sig_SendEditMsg(QString);

protected:
    void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const Q_DECL_OVERRIDE;//自定义QHeaderView的展示
    void mousePressEvent(QMouseEvent*event) Q_DECL_OVERRIDE;
    void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

private:
    QIcon m_icon;
    QPushButton *m_pBtn;
    QLineEdit *m_pLineEdit;
};

#endif // WIDGET_H

源文件:

#include <QDebug>
#include <QPainter>
#include <QMouseEvent>
#include <QInputDialog>

#include "Widget.h"
#include "ui_Widget.h"

Widget::Widget(QWidget *parent) : QWidget(parent)
  , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QStringList headLabels;
    headLabels << "" << "";

    ui->treeWidget->setColumnCount(2);
    ui->treeWidget->setHeaderLabels(headLabels);

    m_pHeader = new CustomHeaderView(Qt::Horizontal,this);
    ui->treeWidget->setHeader(m_pHeader);
    connect(m_pHeader, &CustomHeaderView::Sig_SendEditMsg, [&](const QString &rMsg){
        ui->treeWidget->setHeaderLabel(rMsg);
    });

    connect(m_pHeader, &CustomHeaderView::Sig_ButtonClicked, qApp,&QApplication::quit);

    m_pHeader->setSectionResizeMode(1,QHeaderView::Fixed);
    m_pHeader->setSectionResizeMode(0,QHeaderView::Stretch);
}

Widget::~Widget()
{
    delete ui;
}

CustomHeaderView::CustomHeaderView(Qt::Orientation orientation, QWidget *parent):QHeaderView(orientation, parent)
{
    m_icon.addFile(":/button.png");
    m_pBtn = new QPushButton(this);
    m_pBtn->setFlat(true);
    connect(m_pBtn, &QPushButton::clicked, this, &CustomHeaderView::Sig_ButtonClicked);

    m_pLineEdit = new QLineEdit(this);
    m_pLineEdit->hide();



    setStretchLastSection(false);
}

CustomHeaderView::~CustomHeaderView()
{

}

void CustomHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
    painter->save();
    QHeaderView::paintSection(painter, rect, logicalIndex);
    painter->restore();

    if(0 == logicalIndex && m_pLineEdit->size() != rect.size()) //防止重复设置大小可能造成的编辑框闪影
    {
        m_pLineEdit->resize(rect.size());
    }

    if(1 == logicalIndex)
    {
        QStyleOptionButton option;
        option.initFrom(this);
        option.rect = rect;
        option.icon = m_icon;
        option.iconSize = rect.size();
        option.features = QStyleOptionButton::Flat;

        style()->drawControl(QStyle::CE_PushButton, &option, painter, m_pBtn);
    }
}

void CustomHeaderView::mousePressEvent(QMouseEvent *event)
{
    if((event->button() == Qt::LeftButton) && 1 == logicalIndexAt(event->pos()))
    {
        emit Sig_ButtonClicked();
    }
}

void CustomHeaderView::mouseDoubleClickEvent(QMouseEvent *event)
{
    if((event->buttons() & Qt::LeftButton) && 0 == logicalIndexAt(event->pos()))
    {
        m_pLineEdit->show();
        m_pLineEdit->setFocus();

        m_pLineEdit->disconnect();      //注意:因为QLineEdit是根据焦点判断是否编辑结束的,所以这里要解决重复信号的问题
        connect(m_pLineEdit, &QLineEdit::editingFinished, this, [&]{
            QString strMsg = m_pLineEdit->text();
            emit Sig_SendEditMsg(strMsg);
            m_pLineEdit->disconnect();
            m_pLineEdit->hide();
            m_pLineEdit->clear();
        });
    }
}

 

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果需要在 Qt实现多级跨行合并的表头,可以使用 QHeaderView 的 setSpan() 方法来设置单元格跨度。这个方法接受四个参数,分别是起始列、起始行、跨度列数和跨度行数。因此,我们可以通过调用这个方法来实现单元格的合并。 下面是一个简单的示例代码,演示如何使用 QHeaderView 实现多级跨行合并的表头: ```cpp QStandardItemModel *model = new QStandardItemModel(); // 设置列数和行数 model->setColumnCount(3); model->setRowCount(2); // 设置第一层表头 model->setHeaderData(0, Qt::Horizontal, "A"); model->setHeaderData(1, Qt::Horizontal, "B"); model->setHeaderData(2, Qt::Horizontal, "C"); // 设置第二层表头 model->setHeaderData(0, Qt::Vertical, "1"); model->setHeaderData(1, Qt::Vertical, "2"); // 合并单元格 QHeaderView *headerView = new QHeaderView(Qt::Horizontal, tableView); headerView->setSectionsClickable(true); headerView->setSectionResizeMode(QHeaderView::Stretch); headerView->setSpan(0, 0, 2, 1); // 合并第一列的两行 headerView->setSpan(0, 1, 1, 2); // 合并第二列和第三列的一个单元格 tableView->setHorizontalHeader(headerView); QTableView *tableView = new QTableView(); tableView->setModel(model); // 显示表格 tableView->show(); ``` 在这个示例中,我们首先创建了一个 QStandardItemModel 对象,并设置了两层表头。第一层表头包含了三个列,显示为 "A"、"B" 和 "C"。第二层表头包含了两行,分别显示为 "1" 和 "2"。 然后,我们创建了一个 QHeaderView 控件,并将它设置为水平表头。接着,我们调用 setSpan() 方法来合并单元格。我们合并了第一列的两行,以及第二列和第三列的一个单元格。 最后,我们将这个表头控件设置给 QTableView 控件,然后显示表格。 这样,我们就实现了一个带有多级跨行合并的表头。如果需要更复杂的表头结构,可以继续使用 QHeaderView 的 setSpan() 方法来实现更高级别的合并。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值