我在实现QListView中的自定义窗口小部件渲染时遇到困难。
我目前有一个QListView显示基于PlayQueue的自定义模型QAbstractListModel

使用简单文本可以很好地工作,但是现在我想为每个元素显示一个自定义小部件。
因此,我将QStyledItemDelegate子类化以实现paint方法,如下所示:

void QueueableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
    if (option.state & QStyle::State_Selected)
        painter->fillRect(option.rect, option.palette.highlight());
    QWidget *widget = new QPushButton("bonjour");
    widget->render(painter);
}


选择背景已正确渲染,但未显示任何窗口小部件。我尝试使用简单的QPainter命令(如Qt示例中的命令),但效果很好:

void QueueableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
    if (option.state & QStyle::State_Selected)
        painter->fillRect(option.rect, option.palette.highlight());
    if (option.state & QStyle::State_Selected)
        painter->setPen(option.palette.highlightedText().color());
    painter->setFont(QFont("Arial", 10));
    painter->drawText(option.rect, Qt::AlignCenter, "Custom drawing");
}


所以我尝试了一些更改,例如:


QStyledItemDelegate更改为QItemDelegate
在渲染周围添加painter->save()painter->restore()
将小部件几何设置为可用大小


但是我现在有点卡住了,我在互联网上搜索了一段时间,但是找不到我想要的示例,他们都在谈论编辑小部件(这要容易得多)或自定义绘制的控件(预定义的控件) ,例如进度条)。
但是在这里,我确实需要一个我创建的自定义小部件,其中包含一些布局,标签和像素图。
谢谢你的帮助!

我正在Ubuntu 11.04上将Qt 4.7.3用于GCC。

最佳答案

只是为了完成整个过程:另一人可以找到使用委托将QWidget作为QListView项进行管理的代码。

我终于找到了如何使用它的paint(...)方法使它在QStyledItemDelegate的子类中工作。

在性能上似乎比以前的解决方案更有效,但是该语句需要通过调查setIndexWidget()对创建的QWidget的作用来验证=)。

最后,这是代码:

class PackageListItemWidget: public QWidget


.....

class PackageListItemDelegate: public QStyledItemDelegate


.....

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

// here we have active painter provided by caller

// by the way - we can't use painter->save() and painter->restore()
// methods cause we have to call painter->end() method before painting
// the QWidget, and painter->end() method deletes
// the saved parameters of painter

// we have to save paint device of the provided painter to restore the painter
// after drawing QWidget
QPaintDevice* original_pdev_ptr = painter->device();

// example of simple drawing (selection) before widget
if (option.state & QStyle::State_Selected)
    painter->fillRect(option.rect, option.palette.highlight());

// creating local QWidget (that's why i think it should be fasted, cause we
// don't touch the heap and don't deal with a QWidget except painting)
PackageListItemWidget item_widget;

// Setting some parameters for widget for example
    // spec. params
item_widget.SetPackageName(index.data(Qt::DisplayRole).toString());
    // geometry
item_widget.setGeometry(option.rect);

// here we have to finish the painting of provided painter, cause
//     1) QWidget::render(QPainter *,...) doesn't work with provided external painter
//          and we have to use QWidget::render(QPaintDevice *,...)
//          which creates its own painter
//     2) two painters can't work with the same QPaintDevice at the same time
painter->end();

// rendering of QWidget itself
item_widget.render(painter->device(), QPoint(option.rect.x(), option.rect.y()), QRegion(0, 0, option.rect.width(), option.rect.height()), QWidget::RenderFlag::DrawChildren);

// starting (in fact just continuing) painting with external painter, provided
// by caller
painter->begin(original_pdev_ptr);

// example of simple painting after widget
painter->drawEllipse(0,0, 10,10);
};

08-25 21:10
查看更多