How to use stylesheet colors in a custom QPushButton



  • Hi,
    I want to create a custom style button. This button should have two lines of text with different font styles and alignments. The button should look like the following example:

    |------------------------------------------------------|
    | ICON | firstText bold left aligned                   |
    | ICON |                      secondText right aligned |
    |------------------------------------------------------|
    

    I've created a subclass of QPushButton and wanted to override the paintEvent. The problem is that not all colors defined in the stylesheet are used. (For details please refer to the comments in the code)
    How can I draw the text for the differnt states (hover, focus, pressed) in the color stated in the stylesheet?

    class SettingsButton : public QPushButton
    {
    	Q_OBJECT
    public:
    	explicit SettingsButton(QWidget *parent = 0);
        void setText2(const QString &text1, const QString &text2);
    	QString getText1();
    	QString getText2();
    
    signals:
    
    public slots:
    
    protected:
    	virtual void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE {
    		QRect rect1(55,0,356,25);
    		QRect rect2(55,25,356,25);
    		QFont font;
    
    //        QPushButton::paintEvent(event); //If I use only this function, everything is displayed
                                            //as in the normal paintEvent of the base class.
                                            //The colors of the stylesheet are used for the normal button text,
                                            //but not for my additional text.
    
            //Without the next 4 lines, no stylesheet colors are used.
            //With these 4 lines, only some colors of the stylesheet are used.
            //The background-colors of the following states are correct: Normal, Focus, Hover
            //For the pressed state the background-color of the hover state is used.
            //Text is always displayed in the color of the normal state.
            QStyleOption opt;
            opt.init(this);
            QPainter p(this);
            style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
    
    		QColor color;
    		QPalette palette;
    		palette = this->palette();
            color = palette.color(QPalette::Normal, QPalette::ButtonText);
    
            //displays the correct stylesheet of the button
            qDebug() << "Stylesheet " << this->styleSheet();
            //Stylesheet
            //"QPushButton {image: url(:/Resources/icon.svg); image-position: left; padding: 5px 5px; border: 0px; background-color: darkblue; color: yellow;}
            //QPushButton:focus {image: url(:/Resources/icon.svg); border: 0px;  background-color: red; color: green;}
            //QPushButton:hover {image: url(:/Resources/icon.svg); border: 0px;  background-color: blue; color: red;}
            //QPushButton:pressed {image: url(:/Resources/icon.svg); border: 0px;  background-color: yellow; color: black;}"
    
            qDebug() << "Color " << color.red() << color.green() << color.blue();
            //Color  255 255 0  --> yellow
    
            //Display additional text
            //This text is only displayed in the color of the normal state (yellow)
    		QPainter painter(this);
    		painter.setRenderHint(QPainter::Antialiasing, true);
    		font = painter.font();
    		painter.setFont(QFont(font.family(), font.pointSize(), QFont::Bold));
    		painter.drawText(rect1, Qt::AlignLeft|Qt::AlignVCenter, firstText);
    		painter.setFont(QFont(font.family(), font.pointSize(), QFont::Normal));
    		painter.drawText(rect2, Qt::AlignRight|Qt::AlignVCenter, secondText);
    	}
    
    private:
    	QString firstText;
    	QString secondText;
    };
    

    The *.cpp file:

    SettingsButton::SettingsButton(QWidget *parent) :
    	QPushButton(parent)
    {
    
    }
    
    void SettingsButton::setText2(const QString &text1, const QString &text2) {
    	firstText = text1;
    	secondText = text2;
    	update();	//Update the button
    }
    
    QString SettingsButton::getText1() {
    	return firstText;
    }
    
    QString SettingsButton::getText2() {
    	return secondText;
    }
    

    Thanks in advance for your help.
    Regards,
    Michael



  • The paint event is always painful.
    Have you considered just using 4 QLabels child of the pushbutton layed out in a grid to achieve your goal?



  • Thanks for your answer.
    To use 4 QLabels could help, I will give it a try.
    Is there a posibility to read out the colors and other styles from a button to witch a stylesheet is asigned?

    QPushButton::setStyleSheet(QString("background-color: red ..."));
    

    To set the styles is very easy. But how can I read back the background-color in hovered state for example?
    QPushButton::getStyle(???);


  • Qt Champions 2016

    @M_H
    Hi
    there is styleSheet() which returns the stylesheet string.



  • @mrjj
    You're right, but then I have to analyse the complete QString by hand. I'm looking for something like this:
    color = QPushButton.hover.background;


  • Qt Champions 2016

    @M_H
    as far as I know you cannot access the
    colors etc of the parsed Stylesheet.
    There is no API for it. (sadly)



  • Ok. Then I've also no chance to get the colors of the stylesheet inside the paintEvent. Am I right?
    If it does not work automatically, I've to search for an alternate solution.


  • Qt Champions 2016

    @M_H
    Af far as I know, no.
    It been ask on forum from time to time.
    I never saw a solution.


  • Lifetime Qt Champion

    Hi,

    Are you planning to let somebody change the style of that button ?



  • @SGaist
    Yes, I want to change the colors für hover, focus, pressed with a style sheet. This would be the prefered solution. If I didn't get it work I catch the mouse events and draw the colors as wanted. Changes are a little bit more complicated and not an easy exchange of the stylesheet. Do you have another idea how to solve this problem?
    @VRonin
    I tried your proposal with the 4 Labels in a grid. It is the same behaviour. The text color of the label has always the color specified in QLabel { color: blue; ...}. The Pseudo-States :hover, :focus, :pressed are ignored. The background-color of the state :hover is correct.



  • Thanks to all for your help.
    I didn't get it solved with stylesheets, but I found a solution which works for me:

    class SettingsButton : public QPushButton
    {
        Q_OBJECT
    public:
        explicit SettingsButton(QWidget *parent = 0);
        void setText2(const QString &text1, const QString &text2);
        QString getText1();
        QString getText2();
    
    signals:
    
    public slots:
    
    protected:
        virtual void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE {
            QRect rect1(55,0,356,25);
            QRect rect2(55,25,356,25);
            QFont font;
    
            QPushButton::paintEvent(event); //To draw everything of a normal QPushButton
    
            m_color = QColor(Qt::white);   //same as in stylesheet QPushButton (normal)
            if( QWidget::hasFocus() ) {
                m_color = QColor(Qt::red);   //same as in stylesheet QPushButton:focus
            }
            if( QWidget::underMouse() ) {
                m_color = QColor(Qt::blue);    //same as in stylesheet QPushButton:hover
            }
            if( QPushButton::isDown() ) {
                m_color = QColor(Qt::green);   //same as in stylesheet QPushButton:pressed
            }
    
            //Display additional text
            QPainter painter(this);
            painter.setRenderHint(QPainter::Antialiasing, true);
            painter.setPen(m_color);
            font = painter.font();
            painter.setFont(QFont(font.family(), font.pointSize(), QFont::Bold));
            painter.drawText(rect1, Qt::AlignLeft|Qt::AlignVCenter, firstText);
            painter.setFont(QFont(font.family(), font.pointSize(), QFont::Normal));
            painter.drawText(rect2, Qt::AlignRight|Qt::AlignVCenter, secondText);
        }
    
    private:
        QString firstText;
        QString secondText;
        QColor m_color;
    };
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.