使用 QStyledItemDelegate 绘制 QTreeView 项目

Drawing QTreeView items with QStyledItemDelegate

我已经根据 Qt 示例列表中的 Simple Tree Model Example 创建了一个项目并编辑了它的模型,以便也可以检查一些项目;这是它的样子:

我希望将一些项目稍微向左移动。所以我通过派生 QStyledItemDelegate 创建了一个委托并像这样重新实现 QStyledItemDelegate::paint

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);
}

这样 TreeItem::Type::Checkable 类型的项目将根据 desiredThreshold 常量的值(在本例中为 10 像素)绘制到左侧。

到目前为止一切顺利;一切正常,绘图正确完成。然而...

问题是虽然项目被稍微向左绘制(这没问题),但鼠标事件仍然有效,就好像项目根本没有移动一样;它是这样工作的:

是否可以告诉代表整个项目稍微向左绘制,以便当我单击复选框(也与整个项目一起移动)时模型会正确更新?

原因

您可以更改 ItemViewItem 在屏幕上的呈现方式,但不会更改它对用户操作的响应方式。

解决方案

我建议你重新实现 QStyledItemDelegate::editorEvent; in order to adjust the position of the QRect returned by QStyle::subElementRect when called with QStyle::SE_ItemViewItemCheckIndicator 作为参数。

例子

考虑以下步骤:

  1. 在你的 TreeItemDelegate class
  2. 中添加一个 public editorEvent 方法
  3. QStyledItemDelegate::editorEventdefault implementation 复制到您的代码中
  4. 通过改变

    避免调用QStyledItemDelegate的私有方法
    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
    QStyle *style = widget ? widget->style() : QApplication::style();
    

    QStyle *style = option.widget->style();
    
  5. 通过改变

    调整checkRect的位置
    QRect checkRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, widget);
    

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