在做数据展示时,为了偷懒少布局些界面元素,结果后面发现某部分功能无法很容易的实现,然后想到了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();
});
}
}