问题来自于做选择窗口时的一个简单需求:
你们可以看到它是一个
QListView
显示文件列表,然后选择用户需要的文件,确认并关闭。
原生
QListView
只显示一行数据,在Qt.DisplayRole
中。我需要添加第二行文本,显示文件大小、修改时间、目录等内容
所以在询问ChatGPT和搜索之后,我知道我需要将自己的数据存储在
Qt.UserRole
中应用自定义QStyledItemDelegate
到QListView
,重写它的paint()
方法。
Native
paint()
很好地处理复选框和装饰图标。我只需要在渲染 Qt.DisplayRole
时添加第二行。然后我发现 paint()
渲染项目作为一个整体,我必须从零开始写一切。
我只能从这里找到C++ src:
/*!
Renders the delegate using the given \a painter and style \a option for
the item specified by \a index.
This function paints the item using the view's QStyle.
When reimplementing paint in a subclass. Use the initStyleOption()
to set up the \a option in the same way as the
QStyledItemDelegate.
Whenever possible, use the \a option while painting.
Especially its \l{QStyleOption::}{rect} variable to decide
where to draw and its \l{QStyleOption::}{state} to determine
if it is enabled or selected.
After painting, you should ensure that the painter is returned to
the state it was supplied in when this function was called.
For example, it may be useful to call QPainter::save() before
painting and QPainter::restore() afterwards.
\sa QItemDelegate::paint(), QStyle::drawControl(), QStyle::CE_ItemViewItem
*/
void QStyledItemDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_ASSERT(index.isValid());
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
QStyle *style = widget ? widget->style() : QApplication::style();
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
}
来自PySide6文档:
如果代理不支持你需要的数据类型的绘制或者你想自定义项目的绘制,你需要子类化 QStyledItemDelegate ,并重新实现 paint() 和可能的 sizeHint() 。 paint() 函数为每个项目单独调用,并使用 sizeHint() ,您可以为每个项目指定提示。
重新实现 paint() 时,通常会处理想要绘制的数据类型,并将超类实现用于其他类型。
复选框指示器的绘制由当前样式执行。该样式还指定了为不同数据角色绘制数据的大小和边界矩形。项目本身的边界矩形也是由样式计算的。因此,当绘制已经支持的数据类型时,最好询问这些边界矩形的样式。 QStyle 类描述对此进行了更详细的描述。
如果您希望更改任何由样式计算的边界矩形或复选框指示器的绘制,您可以子类化 QStyle 。但是请注意,重新实现 sizeHint() 也会影响项目的大小。
作为 QT 的新手,我无法处理这么多的 StateFlags 和主题样式,尝试编写一个没有任何 Hover / Selected / OutOfFocus 样式更改的“死” ui.
我终于用愚蠢但有效的方式实现了我的需求:
'\n'
后添加一个Qt.DisplayRole
为一个项目,AlignVCenter | AlignLeft
),super().paint(painter, option, index)
然后 Qt 将以 2 倍行高呈现
DisplayRole
,但第 2 行为空。
painter.drawText()
用option.font
、option.fontMetrics
、从option.rect
我也按照本指南成功绘制了复选框,用python重写了cpp代码逻辑。结果点了之后没有反应。它的状态总是“未检查”。
我的问题是,如何尽可能“本地”实现我的需求?
类似的做法: