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

introducing color to my UI



  • Hi all -

    I've looked at this subject before, but now I need to get serious with it. I'd like to add color to my UI. Specifically, I'd like to set the background color of a row in a QTableView based on the value a column of the QStandardItemModel that it's representing.

    I've read differing opinions on the proper way to do this. Someone suggests changing setdata() on the model; others say that it's inappropriate to touch the model when you're dealing with a change to the UI.

    So...what say you?

    Here's my display (ignore the row highlighting; that's due to selection):
    widget.PNG

    As an example, let's say that I'd like to give a blue background to every row that contains a serial number that is even (divisible by 2). How do I best do this?

    Thanks...



  • @mzimmers said in introducing color to my UI:

    that it's inappropriate to touch the model when you're dealing with a change to the UI.

    Sounds like something I'd say.

    Create a delegate similar to the one below, set the column number that contains the value you want to check, use QAbstractItemView::setItemDelegate to set it to the view

    class LineColorDelegate : public QStyledItemDelegate {
        Q_OBJECT
        Q_DISABLE_COPY(LineColorDelegate)
    public:
        LineColorDelegate(QObject* parent = nullptr)
            : QStyledItemDelegate(parent)
            , m_serialColumn(0)
        {}
        void setSerialColumn(int val)
        {
            if(val>=0)
                m_serialColumn=val;
        }
        int serialColumn() const
        {
            return m_serialColumn;
        }
    private:
        int m_serialColumn;
    protected:
        void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override
        {
            QStyledItemDelegate::initStyleOption(option,index);
            const int serialVal = index.model()->index(index.row(),m_serialColumn,index.parent()).data().toInt();
            if(serialVal%2==0)
                option->backgroundBrush = QBrush(Qt::blue);
        }
    };
    


  • That's a thing of beauty...thanks.

    For my education, how does this method compare/contrast with using roles (something else I read about) for the same purpose? In other words, is there a general guideline about when one is more appropriate?

    Thanks again.



    • When the color is part of the data itself and does not depend on a calculation on another piece of the data
    • For efficiency, when the color changes frequently externally.
      e.g. you have a list of words and a lineedit, when the lineedit changes you want to highlight the words in the list that contain the text of the lineedit. If you manage the background delegate-side you'd need to repaint the whole thing every time the lineedit changes, if you do it data-side you only repaynt the cells that actually changed


  • Good answer, but now I'm not sure I know which is more appropriate for me.

    My app receives messages from various embedded devices. The worker task determines whether the message was received via WiFi or USB, and adds a field to the message, then passes the message to the model for processing. The idea was going to be that if connected via WiFi, I'd use one color for that device in the display; if connected via USB, I'd use another (or no color at all).

    Is the approach you furnished still the favored solution?



  • I'd say in your case the color is the data so I'd just store the QBrush in the Qt::BackgroundRole of the model and use the default delegate


Log in to reply