PDA

View Full Version : why do buttons don't change color?



Raccoon29
11th November 2007, 23:03
Hi everyone.

I'm using Qt4 on Windows and I'm encountering troubles with the buttons colors.
Two questions I have:
1) Even changing the QPalette::Button and QPalette::ButtonText colors of a QPushButton palette, why just the text gets changed and not the background? Do palettes support multiple changes? Here follows the piece of code which changes the palette:

QPalette pal;
pal.setColor(QPalette::ButtonText, Qt::white);
pal.setColor(QPalette::Button, Qt::black);
ui.cmdsounddod->setPalette(pal);

2) To Qt developers: was this palette approach needed? :rolleyes:
Well, I mean, in Qt3 to change a color needed a call to

uiobject->setBackgroundColor(QColor)
and now it needs to pass through the palette that I find a bit complex... :confused:
I wouldn't be surprised if I miss a quicker way to change a ui object color... :o

Thank you in advance,
any help is appreciated

momesana
11th November 2007, 23:54
The problem is that different platforms interpret the Palettes differently. Which color role is used for what is decided by the QStyle. On Linux the Plastique style uses the Button Palette for the color of a button. The Windows style however uses the BaseRole for that purpose. This inconsistent usage of palettes has always been an issue that led to the creation of Qt StyleSheets.

StyleSheets are much simpler and you have guaranties that a color will be like that on every platform (expect MacOSX as of now). The need for having a red button on every platform, was a particular problem that led to the creation of Stylesheets in the first place.:D
You may want to read this about the "Red Pushbutton project": http://chaos.troll.no/~ahanssen/devdays2007/StyleSheets.pdf (http://chaos.troll.no/%7Eahanssen/devdays2007/StyleSheets.pdf)
:D

As of changing the background-color of your button ... try this out:


#include <QApplication>
#include <QtGui>

int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QPushButton* btn = new QPushButton("Press me");
btn->setStyleSheet(
"background:qlineargradient(x1:0, y1:0, x2:0, y2:1,"
"stop: 0 black, stop: 0.4 gray, stop: 0.5 darkgray, stop: 1.0 black);"
"color:yellow; font-size:24px;"
"font-weight:bold; border-radius:10%;"
"margin:10px; border:3px dashed green;"
);
btn->show();
btn->resize(200,80);
return app.exec();
}

This should yield a result like this:
1709

Now tell me, would it have been that easy with Qt3? ;)
Read this for more information: http://doc.trolltech.com/4.3/stylesheet-examples.html#customizing-qpushbutton

wysota
12th November 2007, 00:22
2) To Qt developers: was this palette approach needed? :rolleyes:
Well, I mean, in Qt3 to change a color needed a call to

uiobject->setBackgroundColor(QColor)
and now it needs to pass through the palette that I find a bit complex... :confused:
I wouldn't be surprised if I miss a quicker way to change a ui object color... :o

I'm not Qt developer, but I think I might try to answer that, at least until more appropriate people decide to reply as well.

In Qt3 you had a palette object as well (QColorGroup). There just was a method to quick access the foreground and background component of it.

Raccoon29
13th November 2007, 12:08
Now tell me, would it have been that easy with Qt3? ;)

Oh my! This stylesheet is amazing! Right like a powerfull CSS style! :)
Well... I knew it... there was a quicker way that I didn't know :p
This Qt4 seems to be way more mighty than Qt3!

Thank you for all explanations!
Thank you, thank you, thank you! :D

dyams
16th November 2007, 04:08
BTW, Using stylesheets in place of
setBackgroundColor()... is not too bad,
but my doubt is,
while I am interested in ONLY the background of the widget, WHY should I worry about its margin, border, .... also why should change the look of the widget when it is pressed
QPushButton:pressed(...)??

And to change the background color, they use qlineargradient, I want to set the SPREAD property of the same in the stylesheets. How to I achieve this?

In fact, changing the backcolor through stylesheets is easy but not for all widgets, like QPushButton..

mchara
16th November 2007, 07:05
There just was a method to quick access the foreground and background component of it.

Qt4 still have those methods to access to foreground & background color:


void QWidget::setBackgroundRole ( QPalette::ColorRole role );
void QWidget::setForegroundRole ( QPalette::ColorRole role );

but, there's one method more, that often causes background color isn't applied:


void setAutoFillBackground ( bool enabled );



This property holds whether the widget background is filled automatically.
If enabled, this will cause Qt to fill the background using the widget's background role before invoking the paint event. The background role is defined by the widget's palette.
In addition, Windows are always filled with QPalette::Window, unless the WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
Warning: Do not set this property when using Qt Style Sheets. When using style sheets, the widget is always filled with the "background" property. The "border-radius" property may be used to clip the background.

See, qt assumes that custom backgrounds are rare cases, so to optimize painting they don't draw it at all by default, If you're setting custom background role, you shall probably turn autofillbackground on - I'm nearly sure that's your problems source.

momesana
16th November 2007, 09:41
BTW, Using stylesheets in place of
setBackgroundColor()... is not too bad,
but my doubt is,
while I am interested in ONLY the background of the widget, WHY should I worry about its

You only need to set the properties you are interested it. The example above was a little verbose because I wanted to highlight the possibilities that Qt4 in conjunction with Stylesheets has to offer.



margin, border, .... also why should change the look of the widget when it is pressed
QPushButton:pressed(...)??

You don't have to but then the pressed stage wouldn't look different from the normal state. And you can not except Qt to calculate the highlighted state for a button after custom-painting its background.



And to change the background color, they use qlineargradient, I want to set the SPREAD property of the same in the stylesheets. How to I achieve this?

You can do all the gradient effects offered to you by the QGradient derived classes. Read the respective docs and the examples provided by Qt.




In fact, changing the backcolor through stylesheets is easy but not for all widgets, like QPushButton..
It's actually almost always the easier solution. And it provides the possibility to make an application themable in a very simple manner. And you can set the properties selectively. For example:



QPushButton#OkButton { background-color:yellow; }
would *only* change the background color of Buttons that have "OkButton" set as their object names. Applying stylesheets to the QApplication (qApp->setStyleSheets()) makes the whole application apply the style. just provide a bunch of css files and facilities to load them and you have a stylable program. I think that's pretty amazing.

wysota
16th November 2007, 10:06
In fact, changing the backcolor through stylesheets is easy but not for all widgets, like QPushButton..

Actually this is currently the only possibility to change the background colour of a button in a reliable way. Other solutions (like changing the palette) simply won't work on WinXP, Vista or Aqua.

mchara
16th November 2007, 10:26
Other solutions (like changing the palette) simply won't work on WinXP, Vista or Aqua.

it looks like some styles are using fixed colors, so maybe it's good idea to inherit those styles & fix the problem there once instead of using styleSheets for every single button?

wysota
16th November 2007, 12:00
it looks like some styles are using fixed colors, so maybe it's good idea to inherit those styles & fix the problem there once
No. XP, Vista and Aqua use their native routines to paint the gui and they don't allow changing colours of buttons. The way stylesheets work is that they provide an additional style layer and either do the drawing themselves or pass the call to the original style, depending on what the style is and what the stylesheet contains.


instead of using styleSheets for every single button?

You can apply a stylesheet on the application object and thus change all buttons with a single call.