Unsolved Getting colors from stylesheet in code
-
I have a custom QTreeWidget control in which I modify the color of each item by calling setForeground. Right now I'm using hard coded colors, but I need this to conform to the colors set in the stylesheet instead. Is there a way to programatically get at the colors in the stylesheet? I just need to read the values for normal and disabled
-
@Dan203 said in Getting colors from stylesheet in code:
Is there a way to programatically get at the colors in the stylesheet?
I'm afraid not.
-
Anyway to add a custom property to the stylesheet that I can read in my code then? Like a custom selector?
-
@Dan203
I don't know exactly what you mean. Nothing from stylesheet(s) is accessible back in code, so far as I know. Unless you want to parse the stylesheet at the time you load it and apply it.You can use dynamic properties in stylesheets (https://wiki.qt.io/Dynamic_Properties_and_Stylesheets), https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-using-dynamic-properties, but I don't see how that would relate to your issue.
-
That property thing would work, but it doesn't look like there is a way to set a property on a QTreeWidget item.
Let me explain what I'm doing, maybe there is another way...
So I have a QTreeWidget which is a list of "save profiles". Each profile in the list has a checkbox which indicates whether the profile is displayed in the Save dialog or not. When the checkbox is unchecked I want to change the color of the text to be the disabled color. I can't actually disable the item because that also disables the checkbox and then you can't enabled it. So I just need some way to set the text color for unchecked items to the disabled color. However I'm using stylesheets to change the entire color scheme of my UI, with a user option to pick between several options, so I need some way to pick the color that actually matches the selected stylesheet.
Any ideas on how I could accomplish this? The QTreeWidget is subclassed so I can override the painting if needed. I just need some way to accomplish this effect.
-
@Dan203 said in Getting colors from stylesheet in code:
but it doesn't look like there is a way to set a property on a QTreeWidget item.
That is (unfortunately) true, as a
QTreeWidgetItem
is not aQWidget
.Stylesheets can address items via
QTreeView::item
, optionally followed by certain pseudo-states (selected, hovered etc.), but I don't see that can be used to select arbitrary individual items.For full control over items' display you may need to set your tree widget's
QStyledItemDelegate
viasetItemDelegate()
. @VRonin is your champion if that is required.Alternatively, from what you say you should be able to use the
QTreeWidget
's model to set/return properties such as text color on individual items according to some criteria such as whether it is checked.However, neither of these is going to help getting a desired color from a stylesheet. Stylesheet rules are effectively a "black box" in Qt, you hand the text of the rule over to Qt and no longer know/access anything about it. That's just how it is --- unless you want to try to parse it yourself.
If you do have the text of the stylesheet, it is not robust by any means but you may find using a regular expression to pick out, say, a color in a particular rule is not too difficult and suffices for your purposes.
If you are pre-supplying a certain number of stylesheets of varying color schemes, when user picks a scheme you might use that to "look up" what you need to know from some information you have pre-saved related to the chosen scheme.
-
If you give me a sample stylesheet I can test it but, in theory, this should work:
#include <QApplication> #include <QTableWidget> #include <QStyledItemDelegate> class DisabledCheckDelegate : public QStyledItemDelegate{ #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) Q_DISABLE_COPY_MOVE(DisabledCheckDelegate) #else Q_DISABLE_COPY(DisabledCheckDelegate) #endif public: explicit DisabledCheckDelegate(QObject* parent = nullptr) :QStyledItemDelegate(parent) {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_ASSERT(index.isValid()); QStyleOptionViewItem opt = option; initStyleOption(&opt, index); const QWidget *widget = option.widget; QStyle *style = widget ? widget->style() : QApplication::style(); if(index.data(Qt::CheckStateRole).value<Qt::CheckState>() == Qt::Checked){ style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget); return; } QStyleOptionViewItem disabledOpt = opt; disabledOpt.state &= ~QStyle::State_Enabled; style->drawControl(QStyle::CE_ItemViewItem, &disabledOpt, painter, widget); if (opt.features & QStyleOptionViewItem::HasCheckIndicator) { opt.rect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &opt, widget);; opt.state &= ~QStyle::State_HasFocus; switch (opt.checkState) { case Qt::Unchecked: opt.state |= QStyle::State_Off; break; case Qt::PartiallyChecked: opt.state |= QStyle::State_NoChange; break; case Qt::Checked: opt.state |= QStyle::State_On; break; } style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &opt, painter, widget); } } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); QTableWidget wid(2,1); QTableWidgetItem* item = new QTableWidgetItem; item->setText("Enabled"); item->setCheckState(Qt::Checked); wid.setItem(0,0,item); item = new QTableWidgetItem; item->setText("Disabled"); item->setCheckState(Qt::Unchecked); wid.setItem(1,0,item); wid.setItemDelegate(new DisabledCheckDelegate(&wid)); wid.show(); return a.exec(); }
-
That may ultimately be how I handle it, I was just hoping there was a simpler way. Thanks for explaining
-
@Dan203
All the stylesheet parsing/handling code of stylesheets is done in internal Qt code. You are not the first person who has wished you could access it, but so far as I know that's how it stays. -
I might dig into the Qt source and see if there is some way to hack it to the surface via subclassing. I'll post here if I actually figure out a way to do it.