简体   繁体   中英

Drawing QTreeView items with QStyledItemDelegate

I have created a project based on the Simple Tree Model Example from the Qt examples list and edited its model so that some items can also be checked; this is how it looks like:

在此处输入图片说明

I would like some of the items to be slightly moved to the left. So I created a delegate by deriving QStyledItemDelegate and reimplemented QStyledItemDelegate::paint like this:

void TreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (index.column() == 0) {
        TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
        if (childItem->type() == TreeItem::Type::Checkable) {
            QStyleOptionViewItem opt = option;
            QStyledItemDelegate::initStyleOption(&opt, index);

            const int desiredThreshold = 10;

            opt.rect.setX(opt.rect.x() - desiredThreshold);
            option.widget->style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, option.widget);

            return;
        }
    }

    return QStyledItemDelegate::paint(painter, option, index);
}

This way items of type TreeItem::Type::Checkable will be drawn to the left by the value of the desiredThreshold constant (in this case 10 pixels).

So far so good; everything works well and the drawing is done correctly. However...

The problem is that although the item is drawn slightly to the left(which is ok), the mouse events are still working as if the item didn't move at all; here's how it works:

在此处输入图片说明

Is it possible to tell the delegate that the whole item is drawn slightly to the left so that when I click on the checkbox(which was also moved together with the whole item) the model would be correctly updated?

Cause

You change how the ItemViewItem is rendered on the screen, but not how it responds to user actions.

Solution

I would suggest you to reimplement QStyledItemDelegate::editorEvent ; in order to adjust the position of the QRect returned by QStyle::subElementRect when called with QStyle::SE_ItemViewItemCheckIndicator as an argument.

Example

Consider the following steps:

  1. Add a public editorEvent method in your TreeItemDelegate class
  2. Copy the default implementation of QStyledItemDelegate::editorEvent into your code
  3. Avoid the call to the private method of QStyledItemDelegate by changing

     const QWidget *widget = QStyledItemDelegatePrivate::widget(option); QStyle *style = widget ? widget->style() : QApplication::style(); 

    to

     QStyle *style = option.widget->style(); 
  4. Adjust the position of checkRect by changing

     QRect checkRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, widget); 

    to

     QRect checkRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, option.widget).adjusted(-10, 0, -10, 0); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM