Qt: Background color on QStandardItem using StyleSheet - qt

I have a class that inherits QStandardItem and I put the elements in a QTreeWidget. The class receives notifications from the outside and I want to change the background color of the item based on what happened.
If I do not use stylesheets, it works just fine, like this:
void myClass::onExternalEvent()
{
setBackground(0, QColor(255,0,0)));
}
However, as soon as I put a stylesheet on the QTreeWidget, this has no effect : the stylesheet seems to override the setBackground() call.
So I tried :
void myClass::onExternalEvent()
{
this->setStyleSheet("background-color: red");
}
but this is probably all wrong, it changed the color of some other element on my screen, not sure why.
Does anyone have an idea on how I can alter the background color like with setBackgroundColor but still be able to use stylesheet on my QTreeWidget?

Palettes propagate to the children of a widget, and it's bad to mix and match style-sheet controls and native controls (I do not have a citation for the latter handy, but I have read it in the QT docs somewhere).
That being said, try setting setAutoFillBackground(false) on your QStandardItem derived class.
EDIT: Sorry - also, are you specifying the QTreeWidget in the stylesheet or just setting "background-color:"? If you specify the QTreeWidget only in the stylesheet that might take care of it as well.
QTreeWidget { background-color: white; }
But I think you still have to set the autoFillBackground(false).

Related

Adding new stylesheet parameters for custom Qt widgets

I would like to add stylesheet options for a custom widget I have developed. We have extended the QPushButton to be a different colour and to flash when it is depressed. This has been done by adding a new property, background color down. And we set this in code. But I would like to set this instead using a Qt stylesheet entry, something like
QFlashingButton
{
background-color-down: yellow;
flashing-interval: 5;
}
I can see one way to do this, read out the stylesheet info using the stylesheet() method, then parse it for parameters relevant to my widget and set them. But I am wondering if there is some way to access the code Qt have themselves for processing stylesheets. At first sight of their code this seems perhaps not to be publically available.
As long as the parameter you want to control in the stylesheet is a QProperty, you can set it in the stylesheet using the syntax: qproperty-<PROPERTY_NAME>: <PROPERTY_VALUE>
I don't think property names can actually have dashes in them, so assuming your QProperties on your custom widget are actually backgroundColorDown and flashingInterval, then your stylesheet would look like:
QFlashingButton
{
qproperty-backgroundColorDown: yellow;
qproperty-flashingInterval: 5;
}

Qt StyleSheet system is invalidating QPalette; how to make them work together?

I have in one of my projects a QwtPlot where I want to configure its colors in an harmonious way - that is, e.g., if the background color is white, the axis should be black, etc.. Now I could do this in a "hardcoded way": each time the background color (the reference) is changed, I look at an array of previously defined colors for the axis and set the given color in the array for that axis. But this is quite "out of fashion" and I would like a more automated way.
Seeking help here, Uwe told me to use QwtPlot::setPalette(color), and it works great by itself. The problem is that the QwtPlot is child of a series of QWidget-based widgets whose colors should be configured in a global style sheet file and I noticed that when the style sheet for one of those widgets is configured, it invalidates the QwtPlot's call to setPalette. It is as if I should choose between them: if I'm going to use at least one call to setPalette in a given widget, then none of its parents up to the main widget (a QMainWindow in my case) should be configured with the style sheet system. This seems what this part of the documentation about setPalette is saying:
Warning: Do not use this function in conjunction with Qt Style Sheets.(source)
, but it would seem that was supposed to be the case only when using a global call to setPalette.
So my questions are: is there a way to solve this problem in an harmonious way? Or do I need to abandon the style sheet system for that part of the software and use just palettes instead? I tried to make the style sheet configuration in a more "localized" way - that is trying to say to the system "this stylesheet configuration is only valid for this widget; don't perpetuate it to its child widgets", with no success. If this is really possible (and therefore I probably chosed the wrong syntax), I would like to know.
In your style sheet, use .QWidget {...} rather than QWidget {...} for styles that you don't want subclasses to inherit. If applied to all the QwtPlotparents this will allow you to use setPalette again.
Nothing can save you however if you try to mix style sheets and palettes for the same widget, the style sheet will always supersede it, so beware!
EDIT:
another option is to subclass QwtPlot and use designable properties for the canvas, allowing you to use style sheets to set the property, but also have programmatic access to the value.
#include <QWidget>
#include <QBrush>
#include <qwt_plot.h>
class QPlot : public QwtPlot
{
Q_OBJECT
Q_PROPERTY(QBrush canvasBackground READ canvasBackground
WRITE setCanvasBackground DESIGNABLE true)
public:
QPlot(const QwtText &title, QWidget* parent = nullptr) : QwtPlot(title, parent);
void setCanvasBackground(const QBrush &brush)
{
QwtPlot::setCanvasBackground(brush);
// set the axes color as well, maybe YIQ method?
};
QBrush canvasBackground() const
{
return QwtPlot::canvasBackground;
}
};
In your style sheet you could then set the canvas background with
qproperty-canvasBackground: #000000;
The contrasting color algorithm I think is a bit out of scope for this answer, but these questions may help: Programmatically choose high-contrast colors, How do I invert a colour / color?

Using QApplication::setStyleSheet to override QSS attributes set in Qt

I created a button in Qt and gave it the QSS attribute background-color: gray;, while my external stylesheet has set the QSS attribute of the same button to background-color: blue;. When I run the application the button is gray, even though the style sheet is applied after the QWidget::show() is called and just before QApplication::exec(), as shown below:
MyWidget w;
w.show();
...
app.setStyleSheet("..."); // contents of external stylesheet
return app.exec();
Is it possible to have QApplication::setStyleSheet() override the QSS attributes assigned to a Widget in Qt.
No, it is not possible to override the QSS attributes the way you want, and trust me, you don't want to. It is not the order in which you call setStyleSheet that matters. It is the hierarchy that matters first. The call order matters only on widgets which are situated on the same level of the hierarchy.
The reason is that the widget has its internal style rules defined which override the parent's style thus the application style in your case. It is a hierarchy that is respected. You can look at this in the following way:
Say you have a QWidget with the following child hierarchy:
QWidget
|__QPushButton
|
|__QFrame
| |
| |_QListView
|
|__QProgressBar
Let's say you want to customize the background-color to all the widgets in your hierarchy. If the call to QApplication::setStyleSheet() would overwrite the stylesheet properties for the children, it would be impossible for you to set a custom style for your children. That's why child widget's QSS properties overwrite parent widget's QSS properties.
Look at it like the usual way to look at widgets. QPushButton is shown on top of QWidget. QFrame is shown on top of QWidget. QListView is also shown on top of QWidget. Styles apply the same way.
What I recommend doing is having only one external QSS file in which you define everything you want.
EDIT:
As N1ghtLight pointed out QSS preserves the class inheritance hierarchy so if you set a property for a class all its derived classes will inherit that property. For example if you have the following stylesheet:
QAbstractButton {
background-color: red;
}
QPushButton {
color: blue;
}
All QPushButtons will have the background color red and the text color blue as the QPushButton inherits the background-color property value from QAbstractButton which is its ancestor while QAbstractButtons which are not QPushButtons will have the background color red but the text color will remain unchanged.
The example above used a type selector. You can apply the style to specific objects by using different selector types. You can see different selector types here.

QComboBox AbstractItemView::item

Is there a way I could increase the height of the items, which are listed in a QComboBox control ?
I tried following as suggested here in QTDevNet forums but with no luck
QComboBox QAbstractItemView::item {margin-top: 3px;}
I also tried this, still with no result.
QComboBox QAbstractItemView::item {min-height: 20px;}
Is it possible to achieve this at style-sheet level at all ?
Your style sheet seemed correct, so I tried it. It seems the problem is similar to this one on Qt centre:
QCompleter sets a custom QAbstractItemDelegate on its model and unfortunately this custom item delegate does not inherit QStyledItemDelegate but simply QItemDelegate (and then overrides the paint method to show the selected state).
If you replace the default delegate by a QStyledItemDelegate, your style sheet should work:
QStyledItemDelegate* itemDelegate = new QStyledItemDelegate();
combo->setItemDelegate(itemDelegate);
Important: If you change the model, then that will reset the view's delegate, so the above method needs to be called after any call to setModel().
An alternative solution would be:
ui->comboBox->model()->setData(ui->comboBox->model()->index(-row-, 0), QSize(-width-, -height-), Qt::SizeHintRole);
, where -row- is zero-based item index; -width- and -height- stand for item width hint and height hint, respectively.
QComboBox::item worked for me
So for example, I was trying to change the color of the item when it was disabled, and the following code did the trick.
This one did not work:
QComboBox QAbstractItemView::item:!enabled {
color:red;
}
Instead I used:
QComboBox::item:!enabled {
color:red;
}

Styling QPushButton with CSS?

I'm trying to create a QPushButton that's just got an icon and a constant background color.
So that I can swap out the icon when the user clicks it, without any other apparent effects (this is for a roll-up/roll-down feature). I've added an entry like this to my stylesheet:
QPushButton.ToggleButton {
background-color: #8af;
}
and set the button's class to match, and this does indeed give me the look I want, except that when I click on it the background color changes to a lighter blue, which I don't want. What am I missing?
Edit: I guess I should mention I'm using Qt 4.5 and PyQt 4.6 to do this...
I know people like using stylesheets, but in this situation I think it is just as easy to make a custom button. Define a class that inherits from QAbstractButton, and override the paint() method. In the paint method, fill the rect with your desired background color, and then paint the current icon on top. It might be slightly more complicated if you want the border around the button as well, but not a lot.
Alternately, you could also look at the roles for QPalette, specifically QPalette::Light and QPalette::Midlight, which might be used to adjust the color of the button when pressed.
Answer
Try giving the button an ID with QObject::setObjectName and then applying the style with #idSelector?
In Python the code would probably look something like this:
button = QPushButton(self)
button.setObjectName("ToggleButton")
and stylesheet like this:
#ToggleButton:pressed {
background-color: #8af;
}
Further reading
The QFriendFeed example application at Forum Nokia is using Qt style sheets heavily to customize the UI.
I'm guessing doing background-color: #8af !important; would be too obvious so I'm assuming that doesn't work. It's worth a try if you haven't done it yet.
Otherwise, as noted in this question, there are specific states you can style. Try setting the same background color for the pressed state:
QPushButton.ToggleButton:pressed { background-color: #8af; }
Sorry if I misunderstood. Hope that helps.
open the button's stylesheet in Qt designer and try this:
QPushButton:pressed {
image: url(/path/to/your/file/fileName.png);
}

Resources