Reputation: 1935
I am trying to use a QLinearGradient
to paint a QPushButton
with no success. I have found examples on how to paint it with a solid color. But I have been unsuccessful in finding examples for a color gradient. Moreover, my approach did not work.
Here is my complete example where the solid color push button works and the linear gradient one does not:
#include <QApplication>
#include <QGridLayout>
#include <QLinearGradient>
#include <QPalette>
#include <QPushButton>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
// Create layout
QGridLayout* layout = new QGridLayout;
// Create first button
QPushButton* button_1 = new QPushButton();
layout->addWidget(button_1, 0, 0);
QPalette palette_1 = button_1->palette();
palette_1.setColor(QPalette::Button, Qt::red);
button_1->setPalette(palette_1);
button_1->update();
// Create second button
QPushButton* button_2 = new QPushButton();
layout->addWidget(button_2, 0, 1);
QLinearGradient gradient_button(0, 0, button_2->width(), 0);
gradient_button.setColorAt(0, Qt::white);
gradient_button.setColorAt(1, Qt::black);
QPalette palette_2 = button_2->palette();
QBrush brush(gradient_button);
palette_2.setBrush(QPalette::Button, brush);
button_2->setPalette(palette_2);
button_2->update();
// Create widget
QWidget* widget = new QWidget;
widget->setLayout(layout);
widget->resize(300, 50);
/// Show
widget->show();
// Run
return app.exec();
}
Any ideas on what am I doing wrong?
Upvotes: 3
Views: 1994
Reputation: 11575
Your gradient is configured to go from <0, 0>
to <button_2->width(), 0>
, but at the moment you create your gradient button_2
is not included in any layout: its width will be computed when the parent widget (therefore the layout where the button is) is resized. If you try fixing the width you'll see the gradient works as expected.
QPushButton* button_2 = new QPushButton();
button_2->setFixedWidth(100);
You can use an event filter to watch for the resize and adjust the gradient accordingly:
class ButtonResizeWatcher : public QObject {
protected:
virtual bool eventFilter(QObject* o, QEvent* e) override {
if (e->type() == QEvent::Resize) {
auto button = qobject_cast<QPushButton*>(o);
QLinearGradient gradient_button(0, 0, button->width(), 0);
gradient_button.setColorAt(0, Qt::white);
gradient_button.setColorAt(1, Qt::red);
auto palette = button->palette();
palette.setBrush(QPalette::Button, QBrush(gradient_button));
button->setPalette(palette);
}
return QObject::eventFilter(o, e);
}
};
Use:
ButtonResizeWatcher resize_watcher;
button_2->installEventFilter(&resize_watcher);
Full code can be found in GitHub.
Another option, as commented in a different answer, would be to use the stylesheet (qlineargradient
). It depends on you if you need further control on the brush, such as "show gradient but only until certain width is reached". Also, take into consideration that stylesheets usually conflicts with other QStyle
s (if used).
Upvotes: 3
Reputation: 444
Without a success I've tried it with QPalette and done it successfully using setStyleSheet
:
QPushButton* button = new QPushButton();
QString linearGradient = QString("qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255));");
button->setStyleSheet(QString("background-color: %1").arg(linearGradient));
Also, we can use QString::arg(...)
to set different colors and points for the gradient.
Hope this help you and excuse me for a stupid comment earlier )
Upvotes: 3