Using QStyledItemDelegate to add separators between QTreeWidgetItems



  • I'm trying to add separators (Using QPainter to draw a line) between QTreeWidgetItems in one of my UI classes. The QTreeWidget in question contains user-defined tags. A user can check the box for any QTreeWidgetItem on the list to assign that particular tag.

    Adding separators between items would help the user understand that the root-level tags are unrelated to each other. This is especially important once I add support for sub-tag child nodes. Furthermore, the background color of checked nodes changes to make selected tags easier to see. If two adjacent tags are selected, they sort of blend into each other (separators would fix that problem).

    Since I can't do much to manipulate a QTreeWidgetItem's appearance directly, (i.e. assigning a stylesheet to QTreeWidgetItems like I could do with other QWidgets) I created a delegate by sub-classing QStyledItemDelegate and assigned it to the QTreeWidget in the hope it would offer me greater control over how list items are rendered.

    Here's my code for the delegate class:

    @
    TagListDelegate::TagListDelegate(QObject *parent)
    : QStyledItemDelegate(parent){

    }

    QSize TagListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
    QSize ret = QStyledItemDelegate::sizeHint(option, index);
    ret=ret * 1.3; // add some more padding between items
    return ret;
    }

    void TagListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
    const QModelIndex &index) const{

    QStyledItemDelegate::paint(painter, option, index);
    painter->drawLine(0,0, 500, 0); // just draw a line, I can figure out the proper width later.
    

    }

    TagListDelegate::~TagListDelegate(){

    }@

    Class header:

    @class TagListDelegate : public QStyledItemDelegate
    {

    public:
    TagListDelegate(QObject* parent);
    protected:
    QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
    void paint(QPainter* painter, const QStyleOptionViewItem& option,
    const QModelIndex& index) const;
    ~TagListDelegate();
    };
    @

    The delgate works as-is but it hasn't solved the problem so far. QPainter draws a line for TagListDelegate::paint() but it only draws one line for the entire QTreeWidget instead of adding a line to every QTreeWidgetItem like I thought it would. I've been trying to figure this out for days but I've had no luck; I haven't really used delegates before so it's still new to me.


  • Moderators

    the reason for that is because in the paint() method you draw the line always on the same position.
    You need to do something like this:
    @
    void TagListDelegate::paint(QPainter *painter, const StyleOptionViewItem &option, const QModelIndex &index) const
    {
    QStyledItemDelegate::paint(painter, option, index);
    painter->save();
    QRect r = option.rect;
    painter->translate( r.topLeft() );
    painter->drawLine(0,0, r.width(), 0);
    painter->restore();
    }
    @
    or draw the line with the coordinates according to option.rect.



  • That fixed it. Thanks!

    My code causes the background color of the current item to change when the user selects it as a tag in order to make active tags easier to find in the list. The only problem I have left is setting a different background color using QTreeWidgetItem::setBackgroundColor() somehow overrides the Delegate and causes the separator line below the item in question to disappear. Is there a way around that?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.