重新实现QStyledItemDelegate :: paint - 如何获取子元素坐标?

时间:2016-02-14 11:06:57

标签: c++ ruby qt

借助自定义QStyledItemDelegate::paint方法呈现 QTreeView 。目的是向节点添加图形元素,例如在项目文本周围绘制(和填充)一个框。树项目可能有复选框。

下面的Ruby代码实现了目标,除了我无法获取文本元素的坐标。经验偏移(x = 29; y = 4)用作解决方法。 super方法在框顶部绘制文本。

  • 如何获取文本元素的坐标
  • 这是正确的方法,还是我必须使用 drawText drawControl 而不是调用超类 paint 方法?在这种情况下,如何控制子元素的布局?

(这个问题不是特定于Ruby的。欢迎包含C ++的答案。)

class ItemDelegate < Qt::StyledItemDelegate

  def paint(painter, option, index)

    text     = index.data.toString
    bg_color = Qt::Color.new(Qt::yellow)
    fg_color = Qt::Color.new(Qt::black)
    offset   = Qt::Point.new(29,4)

    painter.save
    painter.translate(option.rect.topLeft + offset)

    recti = Qt::Rect.new(0, 0, option.rect.width, option.rect.height)
    rectf = Qt::RectF.new(recti)

    margin      = 4
    bounding    = painter.boundingRect(rectf, Qt::AlignLeft, text)
    tbox        = Qt::RectF.new(Qt::PointF.new(-margin,0), bounding.size)
    tbox.width += 2*margin

    painter.fillRect(tbox, bg_color)
    painter.drawRect(tbox)
    painter.restore

    super
  end
end

<小时/> 修改:请找self-contained example here in this Gist

1 个答案:

答案 0 :(得分:2)

我在C ++中遇到了同样的问题。不幸的是,option.rect。*属性的解决方法似乎是找到文本坐标的唯一方法。

这是我的代表的绘画方法:

 void ThumbnailDelegate::paint(QPainter *p_painter, const QStyleOptionViewItem &p_option, const QModelIndex &p_index) const
 {
    if(p_index.isValid())
    {
        const QAbstractItemModel* l_model = p_index.model();
        QPen l_text_pen(Qt::darkGray);

        QBrush l_brush(Qt::black, Qt::SolidPattern);

        /** background rect **/
        QPen l_pen;
        l_pen.setStyle(Qt::SolidLine);
        l_pen.setWidth(4);
        l_pen.setBrush(Qt::lightGray);
        l_pen.setCapStyle(Qt::RoundCap);
        l_pen.setJoinStyle(Qt::RoundJoin);

        p_painter->setPen(l_pen);

        QRect l_border_rect;
        l_border_rect.setX(p_option.rect.x() + 5);
        l_border_rect.setY(p_option.rect.y() + 5);
        l_border_rect.setWidth(p_option.rect.width() - 16);
        l_border_rect.setHeight(p_option.rect.height() - 16);

        QPainterPath l_rounded_rect;
        l_rounded_rect.addRect(QRectF(l_border_rect));
        p_painter->setClipPath(l_rounded_rect);

        /** background color for hovered items **/
        p_painter->fillPath(l_rounded_rect, l_brush);
        p_painter->drawPath(l_rounded_rect);

        /** image **/
        QPixmap l_pixmap = bytearrayToPixmap(l_model->data(p_index, ImageRole).toByteArray()).scaled(150, 150, Qt::KeepAspectRatio);

        QRect l_img_rect = l_border_rect;

        int l_img_x = (l_img_rect.width()/2 - l_pixmap.width()/2)+l_img_rect.x();

        l_img_rect.setX(l_img_x);
        l_img_rect.setY(l_img_rect.y() + 12);
        l_img_rect.setWidth(l_pixmap.width());
        l_img_rect.setHeight(l_pixmap.height());
        p_painter->drawPixmap(l_img_rect, l_pixmap);

        /** label **/
        QRect l_txt_rect = p_option.rect;
        l_txt_rect.setX(l_border_rect.x()+5);
        l_txt_rect.setY(l_border_rect.y() + l_border_rect.height() -20);
        l_txt_rect.setHeight(20);
        l_txt_rect.setWidth(l_txt_rect.width()-20);

        QFont l_font;
        l_font.setBold(true);
        l_font.setPixelSize(12);
        p_painter->setFont(l_font);
        p_painter->setPen(l_text_pen);

        QString l_text = l_model->data(p_index, TextRole).toString();
        p_painter->drawText(l_txt_rect, Qt::ElideRight|Qt::AlignHCenter, l_text);
    }
    else
    {
        qWarning() << "ThumbnailDelegate::paint() Invalid index!";
    }
}

我不擅长Ruby,但正如你所看到的,我正在使用drawPath,drawPixmap和drawText。

结果如下:

enter image description here

我认为最好避免从超类调用paint,因为它应该由Qt自动完成,而你可能会在UI生命周期中破坏某些内容。