Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 a QWidget.

    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 via setItemDelegate(). @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.


Log in to reply