在QTableView中某列中添加Button的导致滚动条滚动的时候消失的问题

之前在项目上需要在表格中加入Button是按照以下两个文章的做法:

http://www.cnblogs.com/li-peng/p/3961843.html

http://www.cnblogs.com/li-peng/p/4029885.html

文章的做法是传统通过子类化QItemDelegate类来做的,通过paint函数在某列中画出QPushButton的Style。

但是这么做有一个问题,就是按钮画出来以后,但是拖动QTableView的滚动条的时候,会导致按钮所在的列的部分按钮又消失的问题。

没查到原因,但是最终还是在找到解决方案了。还是子类化QItemDelegate类,但是与之前的两个文章之前的做法有些不同,以下是正确的

代码:

Delegate头文件:

 1 #pragma once
 2 
 3 #include <QStyledItemDelegate>
 4 #include <QString>
 5 #include <QPersistentModelIndex>
 6 
 7 class QStyleOptionButton;
 8 class CTableWidget;
 9 class QPushButton;
10 
11 class AppRepoButtonDelegate : public QStyledItemDelegate
12 {
13     Q_OBJECT
14 
15 public:
16 
17     explicit AppRepoButtonDelegate(QObject *parent = Q_NULLPTR);
18     ~AppRepoButtonDelegate();
19 public:
20     void setText(const QString& text);
21     void setStyleSheet(const QString& qss);
22 
23 signals:
24     void buttonClicked(const QModelIndex& index);
25 public:
26 
27     QWidget* createEditor(QWidget *parent,
28         const QStyleOptionViewItem &option,
29         const QModelIndex &index) const override;
30    void paint(QPainter *painter, const QStyleOptionViewItem &option, 
31         const QModelIndex &index) const override;
32     void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
33 private slots:
34     void cellEntered(const QModelIndex& index);
35     void slotBtnClicked();
36 private:
37     CTableWidget * m_table_view;
38     bool isOneCellInEditMode;
39     QPushButton* m_btn;
40     QPersistentModelIndex m_currentEditedCellIndex;
41     QString m_btnText;
42     QString m_btnQss;
43 };

Delegate类的CPP实现文件:

  1 #include "AppRepoButtonDelegate.h"
  2 
  3 #include <QStyleOptionButton>
  4 #include <QPainter>
  5 #include <QApplication>
  6 #include <QMouseEvent>
  7 #include <QStandardItemModel>
  8 #include <QPushButton>
  9 #include <QTableView>
 10 
 11 #include "CTableWidget.h"
 12 
 13 AppRepoButtonDelegate::AppRepoButtonDelegate(QObject *parent)
 14     : QStyledItemDelegate(parent)
 15 {
 16     CTableWidget *tabView = qobject_cast<CTableWidget*>(parent);
 17     if (tabView)
 18     {
 19         m_table_view = tabView;
 20         m_btn = new QPushButton(QStringLiteral(""), m_table_view);
 21         m_btn->hide();
 22         m_table_view->setMouseTracking(true);
 23         connect(m_table_view, SIGNAL(entered(QModelIndex)),
 24             this, SLOT(cellEntered(QModelIndex)));
 25         isOneCellInEditMode = false;
 26     }
 27 }
 28 
 29 AppRepoButtonDelegate::~AppRepoButtonDelegate()
 30 {
 31 }
 32 
 33 void AppRepoButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
 34 {
 35     int x, y, width, height;
 36     x = option.rect.left() + option.rect.width() / 2 - 20;
 37     y = option.rect.top() + 5;
 38     width = 60;
 39     height = 20;
 40     
 41     m_btn->setGeometry(QRect(x,y,width,height));
 42     m_btn->setText(m_btnText);
 43     m_btn->setStyleSheet(m_btnQss);
 44     if (option.state == QStyle::State_Selected)
 45         painter->fillRect(option.rect, option.palette.highlight());
 46     QPixmap map = QPixmap::grabWidget(m_btn);
 47     painter->drawPixmap(x, y, map);
 48 }
 49 
 50 QWidget* AppRepoButtonDelegate::createEditor(QWidget *parent, 
 51     const QStyleOptionViewItem &option, const QModelIndex &index) const
 52 {
 53     QPushButton * btn = new QPushButton(parent);
 54     connect(btn, &QPushButton::clicked, this, &AppRepoButtonDelegate::slotBtnClicked);
 55     btn->setText(m_btnText);
 56     btn->setStyleSheet(m_btnQss);
 57     return btn;
 58 }
 59 
 60 void AppRepoButtonDelegate::cellEntered(const QModelIndex& index)
 61 {
 62     if (index.column() == 6 || index.column() == 7)
 63     {
 64         if (isOneCellInEditMode)
 65         {
 66             m_table_view->closePersistentEditor(m_currentEditedCellIndex);
 67         }
 68         m_table_view->openPersistentEditor(index);
 69         isOneCellInEditMode = true;
 70         m_currentEditedCellIndex = index;
 71     }
 72     else {
 73         if (isOneCellInEditMode)
 74         {
 75             isOneCellInEditMode = false;
 76             m_table_view->closePersistentEditor(m_currentEditedCellIndex);
 77         }
 78     }
 79 }
 80 
 81 void AppRepoButtonDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, 
 82     const QModelIndex &index) const
 83 {
 84     int x, y, width, height;
 85     x = option.rect.left() + option.rect.width() / 2 - 20;
 86     y = option.rect.top() + 5;
 87     width = 60;
 88     height = 20;
 89     editor->setGeometry(QRect(x, y, width, height));
 90 }
 91 
 92 void AppRepoButtonDelegate::setText(const QString& text)
 93 {
 94     m_btnText = text;
 95 }
 96 
 97 void AppRepoButtonDelegate::setStyleSheet(const QString& qss)
 98 {
 99     m_btnQss = qss;
100 }
101 
102 void AppRepoButtonDelegate::slotBtnClicked()
103 {
104     emit buttonClicked(m_currentEditedCellIndex);
105 }

用法:

1  auto delegateBtn = new AppRepoButtonDelegate(ui->appTable);
2         delegateBtn->setText(QStringLiteral("下载更新"));
3         m_downloadUpdateDelegate = delegateBtn;
4         connect(m_downloadUpdateDelegate, &AppRepoButtonDelegate::buttonClicked,
5             this, &AppRepoPage::slotDownloadUpdateBtnClicked);
6         ui->appTable->setItemDelegateForColumn(
7             6, m_downloadUpdateDelegate); //给第6列添加下载更新按钮的委托

references:

https://stackoverflow.com/questions/12360111/qpushbutton-in-qtableview
https://stackoverflow.com/questions/25337740/how-to-add-qpushbutton-in-qtableview-when-loading-database-by-c
http://www.qtcentre.org/threads/32394-Add-QPushButton-to-cell-in-QTableView
https://forum.qt.io/topic/53467/how-to-add-qpushbutton-in-qtableview

https://stackoverflow.com/questions/43082419/create-pushbuttons-in-qtableview-with-qstyleditemdelegate-subclass/43109044#43109044 

https://qtadventures.wordpress.com/2012/02/04/adding-button-to-qviewtable/

原文地址:https://www.cnblogs.com/foohack/p/8108446.html