PDA

View Full Version : Dynamically changing QLabel background colour



T4ng10r
5th March 2007, 22:16
In GroupBox I've placed few QLabels. Now - depending on which of this labels I click - I want to change background colour of one of those QLabel.
I've tried


QPalette palette = label->palette();
if (somethink)
palette.setColor(label->backgroundRole(),QColor(Qt::blue));
else
palette.setColor(label->backgroundRole(),QPalette::Window);
label->setText(someText);
label->setPalette(palette);
label->setAutoFillBackground(true);
label->update();


In the result - if i click on QLabel which should change background of others - no effect. When label->setAutoFillBackground(true); is set - widget turns him self into black block. When i click on widgets which should change background - then they are changing it to a proper one.

Then I've tried Style sheets. In places where I was changing palette - now I've placed
label->setStyleSheet("QLabel { background-color: blue }"); and where I reset
label->setStyleSheet("");

No difference.
PS. I'm coding under Windows XP. My application is using different styles like QPlastique, QWindows, QMotif - under each of them I see no effect from above code.

Claymore
5th March 2007, 22:29
label->setStyleSheet("QLabel { background-color: blue }");

Have you tried this?


label->setStyleSheet("background-color: blue");

Also, you could create a QSS file where you can specify how the button behaves when you hover and click on it.

No-Nonsense
6th March 2007, 10:39
label->setStyleSheet("QLabel { background-color: blue }"); and where I reset
label->setStyleSheet("");

Try:


"QLabel { background: blue }"

-Jens

smacchia
6th March 2007, 13:43
You can use style sheets as the other folks suggest. But if you want to use palettes, I think what is wrong is where you have:



if (somethink)
palette.setColor(label->backgroundRole(),QColor(Qt::blue));
else
palette.setColor(label->backgroundRole(),QPalette::Window);

Notice in the else branch, you have QPalette::Window which is a role, not a color. So in that line you have 2 roles. Frankly, I'm surprised it even compiles. You need to specify a color, i.e.,

palette.setColor(label->backgroundRole(), QColor(Qt::<somecolor>));
or

palette.setColor(
Qt::Active,
label->backgroundRole(),
QColor(Qt::<somecolor>));
where Qt::Active is a color group.

Carefully review http://doc.trolltech.com/4.2/qpalette.html

It should contain all the info on how to use palettes.

HTH,
Susan

wysota
6th March 2007, 14:17
Notice in the else branch, you have QPalette::Window which is a role, not a color. So in that line you have 2 roles. Frankly, I'm surprised it even compiles.

It compiles because QColor is castable from int (and QPalette::Window is an int) - notice that Qt::red is an int as well and you could write:

palette.setColor(label->backgroundRole(), Qt::red);

You don't need to go through the QColor constructor.

smacchia
6th March 2007, 14:26
Ah you're correct, forgot about that. But that could still be why there is no color change. And while it the code compiles, is logically incorrect.

I've been using palettes for this very thing successfully (but I must admit, I've been using it for everything *but* labels). The app I am working on has MANY custom colors for every concievable role/state, so I've had to use the palette extensively.

wysota
6th March 2007, 14:41
And while it the code compiles, is logically incorrect.
Yes.


I've been using palettes for this very thing successfully (but I must admit, I've been using it for everything *but* labels). The app I am working on has MANY custom colors for every concievable role/state, so I've had to use the palette extensively.

Labels are tricky. This works for all styles I could test (excluding aqua and windowsxp):

#include <QLabel>
#include <QApplication>

int main(int argc, char **argv){
QApplication app(argc, argv);
QLabel label;
label.setText("Testing");
label.setStyleSheet("background-color: red;");
label.setAutoFillBackground(true);
label.show();
return app.exec();
}

This works as well:

#include <QLabel>
#include <QApplication>

int main(int argc, char **argv){
QApplication app(argc, argv);
QLabel label;
label.setText("Testing");
QPalette pal = label.palette();
pal.setColor(label.backgroundRole(), Qt::red);
label.setPalette(pal);
label.setAutoFillBackground(true);
label.show();
return app.exec();
}

smacchia
6th March 2007, 16:14
Good stuff - thanks. I'll be storing this in my arsenal :)

I would bet it's

label.setAutoFillBackground(true);

that is the key.

T4ng10r
6th March 2007, 18:08
Hmm, now I see my mistakes. And, yes, without label.setAutoFillBackground(true/false); it didn't worked.
Thank you all for help.

wysota
6th March 2007, 22:54
It worked for me without the auto fill, but I believe this may be required for WindowsXP style.

jpn
7th March 2007, 10:56
It worked for me without the auto fill, but I believe this may be required for WindowsXP style.
The label is a top level widget and therefore not transparent; "Windows are always filled with QPalette::Window, unless the WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set."

wysota
7th March 2007, 11:05
Correct.
Here is a final working experiment:

#include <QLabel>
#include <QApplication>
#include <QVBoxLayout>

int main(int argc, char **argv){
QApplication app(argc, argv);
QWidget wgt;
QVBoxLayout *l = new QVBoxLayout(&wgt);
QLabel *label = new QLabel;
l->addWidget(label);
label->setText("Testing");
// this:
// label.setStyleSheet("background-color: red;");
// or this:
QPalette pal = label->palette();
pal.setColor(label->backgroundRole(), Qt::red);
label->setPalette(pal);
label->setAutoFillBackground(true); // rem this to see the difference
wgt.show();
return app.exec();
}

TheRonin
17th April 2007, 14:43
I have a related issue and thought it might fit into this thread. I have a comboBox that's supposed to 'blink' red when an item is added to it.

Unfortunately, just getting something that works has proven to be a bit of a pain:



MyClass::MyClass()
{
comboBox->setAutoFillBackground(true);
}
static bool useRed = true;
void MyClass::addItem(QString itemText)
{
comboBox->insertItem(-1, itemText);
comboBox->setCurrentIndex(0);
QTimer::singleShot(1, this, SLOT(blink()));
}

void myClass::blink()
{
if (useRed){
comboBox->setStyleSheet("background-color: red;");
QTimer::singleShot(500, this, SLOT(blink()));
}else
comboBox->setStyleSheet("background-color: yellow;");

comboBox->update();
useRed = !useRed;
}


first time blink is called the background color changes to red, just as expected. The second time around however, the color goes back to the standard grey and subsequent calls have no effect. Am i missing something here?

TheRonin
18th April 2007, 17:02
Perhaps i should have started a new thread instead of just appending an old one? :confused:

jpn
18th April 2007, 17:31
Could you wrap it as a compilable source file so we could test and see ourselves?

TheRonin
19th April 2007, 11:15
Could you wrap it as a compilable source file so we could test and see ourselves?

Sure thing Jpn!

header file:


#include <QMainWindow>
#include <QWidget>
#include <QPushButton>
#include <QComboBox>
#include <QVBoxLayout>

class Gui : public QMainWindow
{
Q_OBJECT
public:
Gui( QWidget * parent = 0 );

private slots:
void blinkMe();
void blinkStyle();
void blinkPalette();
private:
QWidget *centralwidget;
QPushButton *pushButton;
QComboBox *comboBox;
QVBoxLayout *layout;
};


source file:


#include <iostream>
#include <QApplication>
#include <QString>
#include <QTimer>

#include "gui.h"
//
using namespace std;
//
int main(int argc, char ** argv)
{
QApplication app( argc, argv );
Gui gui;
gui.show();
app.connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) );
return app.exec();
}

Gui::Gui( QWidget * parent ) : QMainWindow(parent)
{
this->setObjectName(QString::fromUtf8("MainWindow"));
this->setWindowTitle("main window test");
centralwidget = new QWidget(this);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
this->setCentralWidget(centralwidget);

pushButton = new QPushButton(centralwidget);
pushButton->setObjectName(QString::fromUtf8("pushButton"));
pushButton->setText("blink?");
pushButton->setAutoFillBackground(true);

comboBox = new QComboBox(centralwidget);
comboBox->setObjectName(QString::fromUtf8("comboBox"));
comboBox->setAutoFillBackground(true);

layout = new QVBoxLayout(centralwidget);
layout->addWidget(comboBox);
layout->addWidget(pushButton);

QSize size(322, 149);
size = size.expandedTo(this->minimumSizeHint());
this->resize(size);

connect(pushButton, SIGNAL(clicked()),
this, SLOT(blinkMe()));

}

static int blinkCount = 0;
void Gui::blinkMe()
{
cout << "trying to blink the comboBox..." << endl;;

blinkStyle();
//blinkPalette();
}

void Gui::blinkStyle()
{
if (++blinkCount > 6){
blinkCount = 0;
return;
}

QWidget* blinkable = comboBox;

if (blinkCount % 2){
//qApp->setStyleSheet("QComboBox#comboBox { background-color: yellow }");
blinkable->setStyleSheet("background-color: yellow");
}else{
//qApp->setStyleSheet("QComboBox#comboBox {}");
blinkable->setStyleSheet("");
}
blinkable->update();

QTimer::singleShot(200, this, SLOT(blinkStyle()));

cout << "blink style! " << blinkable->styleSheet().toStdString() << endl;
}

void Gui::blinkPalette()
{
static QColor oldBaseColor;
static QColor oldHighlightColor;

if (++blinkCount > 6){
blinkCount = 0;
return;
}

QWidget* blinkable = comboBox;
QPalette palette = blinkable->palette();

if (blinkCount % 2){
oldBaseColor = blinkable->palette().color(QPalette::Base);
palette.setColor(QPalette::Base, Qt::yellow);

oldHighlightColor = blinkable->palette().color(QPalette::Highlight);
palette.setColor(QPalette::Highlight, Qt::yellow);
}else{
palette.setColor(QPalette::Base, oldBaseColor);
palette.setColor(QPalette::Highlight, oldHighlightColor);
}
blinkable->setPalette(palette);
blinkable->update();

QTimer::singleShot(200, this, SLOT(blinkPalette()));

cout << "blink palette! " << endl;
}
//


The above example has three test cases.
1) blinking the comboBox's style sheet. To do so, make sure blinkMe() calls blinkStyle() and that blinkStyle() sets the blinkable-widget's style sheet. This is the default.

2) blinking the application's style sheet. Call blinkStyle() and make sure the call to qApp is made instead of to the blinkable-widget.

3) blinking the comboBox's palette. To do so, call blinkPalette() instead of blinkStyle().

Expected results:
All three cases should cause the comboBox's background to blink yellow three times before turning white again.

Actual results:
Only the last two cases behave as expected. The first case causes the comboBox to blink yellow only once before turning white again, regardless of what the secondary color is set to.

jpn
19th April 2007, 11:46
Hmm, maybe a problem with parsing/applying the style sheet? Passing the same style sheet to the combo box than is passed to the application works also.

Edit: Oh, and by the way, please attach large files instead of pasting them as code blocks. Copy-pasting from the code block (http://www.qtcentre.org/forum/f-feedback-13/t-copy-paste-of-code-blocks-845-post34804.html) is inconvenient because of all the extra line number and line breaks.

TheRonin
19th April 2007, 13:01
Hmm, maybe a problem with parsing/applying the style sheet? Passing the same style sheet to the combo box than is passed to the application works also.

But it's strange that it won't work properly for the comboBox since setting the pushButton as the blinkable object gives the expected behavior. Is there any obvious reason why applying the stylesheet directly to the comboBox won't work? Did the example behave as expected for you or did you experience the same behavior? Is this a bug perhaps?


Edit: Oh, and by the way, please attach large files instead of pasting them as code blocks. Copy-pasting from the code block (http://www.qtcentre.org/forum/f-feedback-13/t-copy-paste-of-code-blocks-845-post34804.html) is inconvenient because of all the extra line number and line breaks.

Ok, thanks for the heads-up, i'll attach files in the future.

jpn
19th April 2007, 13:18
But it's strange that it won't work properly for the comboBox since setting the pushButton as the blinkable object gives the expected behavior. Is there any obvious reason why applying the stylesheet directly to the comboBox won't work? Did the example behave as expected for you or did you experience the same behavior? Is this a bug perhaps?
Yeah, I experienced the same and I'd call it a bug. Anyway, what I meant with my previous post was that for me it actually works directly for the combobox in case the style sheet is passed in a same way than you pass it to the application eg. including the selector:


// blinkable->setStyleSheet("background-color: yellow");
blinkable->setStyleSheet("QComboBox{background-color: yellow}"); // <-- works

TheRonin
19th April 2007, 13:47
You're right, that does work. I'll do it that way for now then. Thanks! :D