Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to change the color of QStyledOptionButton's background?



  • This question I had asked on this forums , Please belive me that I had looked the method everwhere,even i search keyword"QStyledOptionButton" on this forums and I read very article tha's i can find...

    There is a table,one column of this table is show the switch of a group devices,and user need clicked this column to control the device,the table looks like this
    alt text

    This programme i use the "QTableView" + "QAbstractTableModel" to show data,and use "QStyledItemDelegate" to show a button on the table.

    devices_TableView->setDelegateForColumn(2,new SwitchDelegate);
    

    the SwitchDelegate inheritens QStyledItemDelegate,and I reimplement paint(); to draw button on the table.

    void SwitchDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
        QStyleOptionButton btn;
        btn.rect = option.rect;
        btn.state |= QStyle::State_Enabled;
        btn.text = index.model()->data(index).toBool() ? tr("Running") : tr("Stop");
        if(option.widget != NULL)
        {
            QApplication::style()->drawControl(QStyle::CE_PushButton,&btn,painter);
        }
    }
    

    Now the question is how to set the background's color of the QStyleOptionButton;
    plan A

        if(option.widget != NULL)
        {
             painter->setBackgroundBrush(QBrush(QColor(Qt::green)));
            QApplication::style()->drawControl(QStyle::CE_PushButton,&btn,painter);
        }
    

    It doesn't work..

    Plan B
    In the constructor of SwitchDelegate,I add an QPushButton

    gb_PushButton = new QPushButton;
    gb_PushButton->setStyleSheet(tr("background-color:green"));
    

    and in the paint()

        if(option.widget != NULL)
        {
            QApplication::style()->drawControl(QStyle::CE_PushButton,&btn,painter,gb_PushButton);
        }
    

    I know there is some leak on constructor,I want to fix the leak after i can change the color of the background of th QStyleOptionButton successful,but as you see,it doesn't work....

    It can't instead the button by a pixmap,becase my boss don't agree the plan......

    How to change the color of QStyledOptionButton's background?


  • Moderators

    @qazaq408

    1. why did you set your fist thread to solved when it seems it isn't?
    2. why creating a new thread instead continuing the old thread?
    3. if you just try to change the background color and want the native appearance to remain this wont't work. The native style gives no possibility to just change the background color.

    If you want (3) then you need to do this:

    1. create a QPushButton* (just for rendering)
    2. hide the pushbutton
    3. create a QGraphicsColorizeEffect and assign it to the pushbutton (with QWidget::setGraphicsEffect())
    4. in the paint() method set the text on the pushbutton and the color on the effect correspondingly and render the button with QWidget::render() - you may need to translate the painter to option.rect.topLeft

    untested and thus may need some minor tweaks



  • @raven-worx

    How to "render the button with QWidget::render() "??

    QStyleOptionButton btn;
    btn.render()??


  • Moderators

    @qazaq408 said in How to change the color of QStyledOptionButton's background?:

    How to "render the button with QWidget::render() "??

    take a look at the docs.

    pushbutton->render( painter ); // use the painter passed to the paint() method
    


  • @raven-worx
    looks like this ?

    SwitchDelegate::ButtonDelegate(QObject* parent):
        QStyledItemDelegate(parent),
        bg_PushButton(new QPushButton),
        bg_GraphicsColorizeEffect(new QGraphicsColorizeEffect)
    {
        bg_GraphicsColorizeEffect->setColor(QColor(Qt::red));
        bg_PushButton->setGraphicsEffect(bg_GraphicsColorizeEffect);//a button and a GraphicsColorizeEffect
    }
    
    void SwitchDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
        QStyleOptionButton btn;
        btn.rect = option.rect;
        btn.state |= QStyle::State_Enabled;
        btn.text = index.model()->data(index).toBool() ? tr("Running") : tr("Stop");
        if(option.widget != NULL)
        {
            bg_PushButton->render(painter);  //send the painter
            QApplication::style()->drawControl(QStyle::CE_PushButton,&btn,painter);
        }
    }
    

    Is there any question because it doesn't work?


  • Moderators

    @qazaq408
    Forget about the button styleoption (for the reason i mentioned before)!

    try this:

    void SwitchDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
        bg_PushButton->resize( option.rect.size() );
        bg_PushButton->setText( index.model()->data(index).toBool() ? tr("Running") : tr("Stop") );
    
        painter->save();
           painter->translate( option.rect.topLeft() );
           bg_PushButton->render( painter );
        painter->restore();
    }
    


  • @raven-worx
    。。。。。。。。。。。。。。。。。。where is the button?
    0_1531994599207_2.png


  • Moderators

    @qazaq408
    ok, seems QWidget::render() doesn't support graphics effects after all.

    Nevertheless here you have a (tested/working) alternative which does the same what the QGraphicsColorizeEffect does:

    ButtonDelegate::ButtonDelegate(QObject* parent)
        : QStyledItemDelegate(parent)
    {
        bg_PushButton = new QPushButton;
        bg_PushButton->hide();
    }
    
    ButtonDelegate::~ButtonDelegate()
    {
        delete bg_PushButton;
    }
    
    void ButtonDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
        QColor overlayColor(255,0,0,100); // semi-transparent red
    
        bg_PushButton->resize( option.rect.size() );
        bg_PushButton->setText( index.model()->data(index).toBool() ? tr("Running") : tr("Stop") );
    
        QPixmap pix(option.rect.size());
            pix.fill(Qt::transparent);
        QPainter btnPainter(&pix);
        // draw button into pixmap first
        bg_PushButton->render(&btnPainter);
        // draw overlayColor over the painted button pixels
        btnPainter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
        btnPainter.fillRect(QRect(QPoint(0,0),pix.size()), overlayColor);
        btnPainter.end();
    
        painter->save();
            painter->translate( option.rect.topLeft() );
            painter->drawPixmap(0,0,pix);
        painter->restore();
    }
    

    If you dont like the result and can live with a non-native style of the button you can apply a stylesheet (like you've already done) and draw the button like in my previous example (just without the graphics effect).



  • @raven-worx
    Thank you, you are a lifesaver. I would have your babies if I was a woman......


Log in to reply