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

Work around for changing tool button's background color



  • Hello all,

    I was wondering if there are any good work around for changing the background color of a QToolButton?

    Currently, I am using the style sheet to change the background. However, I need to remove the border to have the color displayed. But doing that, the button no longer looks like a button.

    I was thinking that I could make the background transparent and have a color label behind the button that changes colors. Not sure if this is the best approach but I wanted to see if any has any other better ideas?

    Thank you


  • Moderators

    You can change background color in QPalette, then apply it to your tool button. So something like:

    QToolButton *button = ...
    QPalette palette = button.palette();
    palette.setBrush(QPalette::Base, QColor(Qt::red));
    palette.setBrush(QPalette::Button, QColor(Qt::red));
    button.setPalette(palette);
    


  • @sierdzio

    Thank you for the tip. I have tried various combinations of these:

      p_deactiveColor.setBrush(QPalette::Base, QColor(Qt::red));
      p_deactiveColor.setBrush(QPalette::Button, QColor(Qt::red));
      p_deactiveColor.setBrush(QPalette::Window, QColor(Qt::red));
      p_deactiveColor.setBrush(QPalette::WindowText, QColor(Qt::red));
    
        ui->cupExtendButton->setPalette(p_deactiveColor);
    

    And on the form only the right and left edges are being colored red. Is there another property that I need to set?


  • Lifetime Qt Champion

    Hi
    You can just give it border back but i suspect its something else you mean
    since using a stylesheet did not do what you wanted?
    alt text



  • @mrjj Do you know what the CSS Styling is for the default border? I would like to keep everything about the button the same except for changing the background color


  • Lifetime Qt Champion

    @Omni_Philm
    Hi
    Sadly its not a stylesheet for the original border.
    Its draw by the QStyle for the used platform.

    The paint event looks like this

    void QToolButton::paintEvent(QPaintEvent *)
    {
        QStylePainter p(this);
        QStyleOptionToolButton opt;
        initStyleOption(&opt);
        p.drawComplexControl(QStyle::CC_ToolButton, opt);
    }
    
    

    But on windows os, it seems to ignore any palette change and i think its not using it for the background.
    At least i could not make it change.

    If you can live with text also getting colored, you could do

    #include <QToolButton>
    #include <QStyleOptionToolButton>
    #include <QStylePainter>
    
    class ColorButton : public QToolButton
    {
        Q_OBJECT
    public:
        explicit ColorButton(QWidget *parent = nullptr) : QToolButton(parent) {}
    protected:
        virtual void paintEvent(QPaintEvent *) override
        {
            QStylePainter p(this);
            QStyleOptionToolButton opt;
            initStyleOption(&opt);        
            p.drawComplexControl(QStyle::CC_ToolButton,   opt);
            p.setBrush(QColor(255,0,0,100));
            p.setPen(Qt::NoPen);
            p.drawRect(4,4,width()-8,height()-8);
        }
    };
    

    First draw the button normally and then put transparent rect on top.

    result:
    alt text



  • @mrjj Thanks for the tip.

    I am not so sure about subclassing. I have a number of buttons that need this. I already am subclassing the lineEdit button to create a clickable signal. And replacing that with the one that I place in the designer can get a little hairy.

    Anyways, I wouldn't mind the rectangle idea but the buttons are within a layout. Isn't the positional coordinates referenced to the layout?

    I am surprised that this issue exists? Would this be a "bug" within the library itself or could I be doing something incorrectly? I think that I am going to create a simple test program to demonstrate what is happening. I feel that the QPalette code should be working correctly?


  • Lifetime Qt Champion

    @Omni_Philm said in Work around for changing tool button's background color:

    And replacing that with the one that I place in the designer can get a little hairy.
    Actually, if you use the promotion feature its pretty easy if you use UI files.
    https://doc.qt.io/qt-5/designer-using-custom-widgets.html

    -Isn't the positional coordinates referenced to the layout?

    Nope its drawn on top so its 100% fixed to the button so layouts etc is not an issue.

    -I feel that the QPalette code should be working correctly?
    Well its not all QStyles that use the palette on all platforms.



  • @mrjj

    Lets explore the rectangle option, how do I fix it to a particular button?


  • Lifetime Qt Champion

    @Omni_Philm
    hi
    its not fixed to it. its painted on top.



  • @mrjj said in Work around for changing tool button's background color:

    Q_OBJECT
    public:
    explicit ColorButton(QWidget *parent = nullptr) : QToolButton(parent) {}
    protected:
    virtual void paintEvent(QPaintEvent *) override
    {
    QStylePainter p(this);
    QStyleOptionToolButton opt;
    initStyleOption(&opt);
    p.drawComplexControl(QStyle::CC_ToolButton, opt);
    p.setBrush(QColor(255,0,0,100));
    p.setPen(Qt::NoPen);
    p.drawRect(4,4,width()-8,height()-8);
    }

    @mrjj

    So I finally had a chance to try out your code. I think that it holds promise but the text will need to be black. Is there any way that I can force draw the text on foreground for everything?

    Also, the pic you have in shows that the text is not really colored with red. However, for me, the text is colored with red but the black is seeping through?



  • Any thoughts?


  • Lifetime Qt Champion

    @Omni_Philm
    Hi
    The overlay is transparent so it only color the black text a bit.
    The (QColor(255,0,0,100)); , the last 100 is how trans it is.

    Well you could remove the text from opt. (set to QString() )
    so there is no text for
    p.drawComplexControl(QStyle::CC_ToolButton, opt);
    to draw
    and then use p.drawText
    after
    p.drawRect
    to have text on top.
    However, if u use any text-align etc on the button, those will break unless you handle that too for the
    custom drawing.



  • @mrjj

    Hello, I am trying to use the drawText function. Here is what I have so far:

    p.setPen(QColor(0,0,0));
    p.setFont(this->font());
    p.drawText(this->frameGeometry(), Qt::AlignCenter, tempText);
    

    What happens is that no text is actually drawn. I figured I would use a rectangle on the QToolButton to bind the text to. That way, I can preserve my alignment.


  • Lifetime Qt Champion

    @Omni_Philm
    what do u set tempText too ?



  • @mrjj

    Oops, forgot to include that line in the example:

    but

    tempText = opt.text;
    

    Edit:

    here is the full drawing code:

            QString tempText;
            QStylePainter p(this);
            QStyleOptionToolButton opt;
            initStyleOption(&opt);
            tempText = opt.text;
            opt.text = QString();
            p.save();
            p.drawComplexControl(QStyle::CC_ToolButton, opt);
            p.setBrush(QColor(255,0,0,100));
            p.setPen(Qt::NoPen);
            p.drawRect(4,4,width()-8,height()-8);
    
         //   p.setBrush(QColor(0,0,0));
            p.setPen(QColor(0,0,0));
    
            p.setFont(this->font());
    
            p.drawText(this->frameGeometry(), Qt::AlignCenter, tempText);
            p.restore();
    


  • Any thoughts?



  • Ok, I got, had to change one of the lines of code to:

    p.drawText(this->contentsRect(), Qt::AlignCenter, tempText);


Log in to reply