How to render a red push button using QStyle.drawControl()?

12.3k views Asked by At

With the following code I tried to render a red push button using QStyle.drawControl():

#include <QtCore/QtCore>
#include <QtGui/QtGui>

class Widget : public QWidget
{
    virtual void paintEvent(QPaintEvent* event)
    {
        QStyleOptionButton opt;
        opt.palette = QPalette(Qt::red);
        opt.state = QStyle::State_Active | QStyle::State_Enabled;
        opt.rect = QRect(50, 25, 100, 50);
        QPainter painter(this);
        style()->drawControl(QStyle::CE_PushButton, &opt, &painter);
    }
};

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    Widget w;
    w.resize(200, 100);
    w.show();
    return app.exec();
}

However I get the following result:

enter image description here

How do I render a red push button using QStyle.drawControl()?

I'm using Qt 4.8.1 and Visal Studio 2010 on Windows XP.

2

There are 2 answers

0
alexisdm On BEST ANSWER

The buttons are drawn by the native style engine, so the palette might not be used at all (see that question from the FAQ).

You can use an actual button with a stylesheet that you pass as the last parameter to the own button's style drawControl function.

class Widget : public QWidget
{
  // To allow the automatic deletion without parenting it
  QScopedPointer<QPushButton> button;
public:
    Widget() : button(new QPushButton) {
      button->setStyleSheet("background-color: red");
    }
    virtual void paintEvent(QPaintEvent* event)
    {
        QStyleOptionButton opt;
        opt.state = QStyle::State_Active | QStyle::State_Enabled;
        opt.rect = QRect(50, 25, 100, 50);
        QPainter painter(this);
        button->style()->drawControl(QStyle::CE_PushButton, &opt, &painter, 
                                     button.data());
    }
};

But you will loose the native style, so you'll have to fake it (bali182's answer might be useful for that part).

Or you can use the same button with colorize effect and call its render() function to paint it:

Colorized Button

class Widget : public QWidget {
    QScopedPointer<QPushButton> button;
public:
    Widget() : button(new QPushButton) {
        QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect(button.data());
        effect->setColor(Qt::red);
        button->setGraphicsEffect(effect);
    }
    virtual void paintEvent(QPaintEvent* event) {
        button->setFixedSize(100, 50);
        button->render(this, QPoint(50, 25));
    }
};
1
Balázs Édes On

What you are trying to do, seems overly complicated. If you just want a red button, why not use the setStyleSheet() method of the QPushButton? It takes a QString, and you can define your button similar to CSS. Here i created you a red button, similar to the XP ui buttons:

QPushButton 
{ 
    background: qlineargradient(x1:0,y1:0,x2:0,y2:1, stop:0 #f4a3a3,stop: 1 #cc1212);
    border-width: 1px; 
    border-color: #d91414; 
    border-style: solid; 
    padding: 5px; 
    padding-left:10px; 
    padding-right:10px; 
    border-radius: 3px; 
    color:#000;
}

QPushButton:hover
{
    border-color: #e36666;
} 

QPushButton:pressed 
{
    background:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop: 0 #de8383, stop: 1 #ad0C0C); 
    border-color: #d91414;
}

Now you just need to pass the code above as a string to your buttons setStyleSheet() method. If you want to create a button widget, what is red by default, then extend the QPushButton class, create a static QString field with the content above, and set the button as stylesheet in the constructor.

More easy to understand examples on stylesheets: Stylesheet Examples