qtqpushbutton

Show push button with "pressed" state in QTableView


I have created a delegate to show push buttons in a QTableView. It looks like this (last two columns):
enter image description here

Here's the code for the delegate's paint method:

void PushButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                               const QModelIndex &index) const
{
    QStyleOptionButton buttonOption;
    buttonOption.state = QStyle::State_Enabled;
    buttonOption.text = this->text;
    buttonOption.rect = option.rect.adjusted(1, 1, -1, -1);
    QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
}

I'm using the table view's clicked signal to capture the clicks on the buttons and that works fine. How can I tweak the delegate so that the buttons look pressed when clicking on them?


Solution

  • Looks like flag QStyle::State_Sunken makes button visually pressed. So try

    buttonOption.state = QStyle::State_Enabled | QStyle::State_Sunken;
    

    EDIT:

    You can implement button clicking painted by delegate with changing data of QTableWidgetItem (if it was created before). For example, let's use Qt::CheckStateRole for passing a pressed state (or use any other role like Qt:UserRole + 1). In this case your paint method will be

    void WidgetPixmapDelegate::paint(QPainter *painter,
                                     const QStyleOptionViewItem &option,
                                     const QModelIndex &index) const
    {
        QStyleOptionButton buttonOption;
        bool isPressed = index.data(Qt::CheckStateRole).toBool();
        if (isPressed)
        {
            buttonOption.state = QStyle::State_Enabled | QStyle::State_Sunken;
        }
        else
        {
            buttonOption.state = QStyle::State_Enabled;
        }
        buttonOption.text = "Text";
        buttonOption.rect = option.rect.adjusted(1, 1, -1, -1);
        QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
    }
    

    So when you will set Qt::CheckStateRole data button will be painted as pressed.

    For processing mouse event subclass QTableWidget and reimplement mouse events you need.

    class ClickTableWidget : public QTableWidget
    {
        Q_OBJECT
    public:
        explicit ClickTableWidget(QWidget *parent = 0);
    
    protected:
        void mousePressEvent(QMouseEvent *event);
        void mouseReleaseEvent(QMouseEvent *event);
    
    signals:
    
    public slots:
    
    };
    
    void ClickTableWidget::mousePressEvent(QMouseEvent *event)
    {
        QTableWidgetItem *item = itemAt(event->pos());
        if (item)
        {
            //check column item->column()
            item->setData(Qt::CheckStateRole, true);
        }
    }
    
    void ClickTableWidget::mouseReleaseEvent(QMouseEvent *event)
    {
        QTableWidgetItem *item = itemAt(event->pos());
        if (item)
        {
            item->setData(Qt::CheckStateRole, false);
        }
    }
    

    Of course this is a primitive example and it does not check drag behaviour, mouse buttons and does not implement hover animation.