在QListWidget的QStyledItemDelegate中,如何绘制所选项以匹配标准列表?

时间:2012-09-24 15:55:07

标签: c++ qt delegates

我的QList小部件有一个QStyledItemDelegate:

class MappingDisplayWidgetDelegate: public QStyledItemDelegate
{
    Q_OBJECT
public:
    MappingDisplayWidgetDelegate(QObject *parent=NULL);
    virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
    virtual QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
};

它的绘画方法如下:

void MappingDisplayWidgetDelegate::paint ( QPainter * painter,
                                           const QStyleOptionViewItem & option,
                                           const QModelIndex & index ) const
{
    if (option.state & QStyle::State_Selected)
        painter->fillRect(option.rect, option.palette.highlight());
    else if (option.state & QStyle::State_MouseOver)
        painter->fillRect(option.rect, option.palette.midlight());


    QFontMetrics fm(option.font);

    QString filename = index.data(Qt::DisplayRole).toString();

    QRect outline = option.rect;
    int outmid = outline.center().y();

    QRect fnBound = fm.boundingRect(filename);
    int fnBoundMid = fnBound.center().y();
    fnBound.moveLeft(outline.left());
    fnBound.translate(0, outmid - fnBoundMid);

    painter->drawText(fnBound, Qt::AlignVCenter | Qt::AlignLeft, filename);

}

现在这样可行,但State_Selected和State_MouseOver的处理不会产生与默认列表相同的结果。这是左边上面代码的屏幕截图(我在Win7系统上运行),右边是标准的QListWidget。你可以看到QListWidget有很好的渐变,而我的项目只有简单的颜色。

enter image description here

我想绘制我的项目以正确匹配标准小部件,但我无法弄清楚如何。我没有看到任何可以提供我需要的信息的选项。

编辑添加: 请注意,这是一个有点玩具的例子。除了一个字符串之外,真正的代码还有许多其他东西,并且具有适当的(和工作)sizeHint函数。这只是一个展示问题的玩具。

3 个答案:

答案 0 :(得分:1)

在用于绘制该元素的source code中,进行以下调用:

// draw the background
proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, widget);

我怀疑你可能想做类似以下的事情:

style().drawPrimitive(QStyle::PE_PanelItemViewItem, option, painter, NULL);

您可能需要使用option参数来获取正确的矩形目标。不幸的是,我现在使用的计算机并没有设置为测试任何这些,所以YMMV。

答案 1 :(得分:1)

我有同样的问题 - 我希望有一个完全自定义的绘画功能,但利用内置的漂亮选择绘画。我已尝试过以下代码,到目前为止,我发现它效果很好,没有任何负面影响:

void MassIndexItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const {
    QStyledItemDelegate::paint(painter, option, QModelIndex());
    //Above, note that rather than passing >index< to the inherited function, I pass a default, invalid index.
    //Since my model's data() function returns an empty QVariant for invalid indexes,
    //I get the default selection painting, but no other data is painted in any way.

    //Below, I can do whatever painting I want and it will show up on top of the pretty selection paint
    painter->drawEllipse(option.rect);
}

答案 2 :(得分:0)

我详细说明这是一个可用的解决方案,虽然它不是一个很好的解决方案。

如果我没有在项目的DisplayRole中放置任何东西,那么我可以调用底层的QStyledItemDelegate :: paint例程,它只会绘制正确的背景,因此:

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

    QFontMetrics fm(option.font);

    QString filename = index.data(Qt::UserRole).toString();

    QRect outline = option.rect;
    int outmid = outline.center().y();

    QRect fnBound = fm.boundingRect(filename);
    int fnBoundMid = fnBound.center().y();
    fnBound.moveLeft(outline.left());
    fnBound.translate(0, outmid - fnBoundMid);

    painter->drawText(fnBound, Qt::AlignVCenter | Qt::AlignLeft,
                      filename);
}

我不喜欢这样,我会暂时尝试戴夫的建议,但如果一个人卡住,这似乎确实有效。在不利方面,这意味着您无法使用DisplayRole,因此您无法在QListWidget中使用findItems。