I am attempting to use a QStyledItemDelegate
with my QListView
to display rich text in the items.
The first time the item is painted its height is too small. If I then mouse over the item it gets repainted with the correct height. Below are screenshots of the initial paint and repaint.
How can I get the initial paint to be the right height?
Example code that demonstrates the issue:
from PySide2 import QtCore, QtGui, QtWidgets
class RichTextItemDelegate(QtWidgets.QStyledItemDelegate):
def __init__(self, parent=None):
super(RichTextItemDelegate, self).__init__(parent)
self.doc = QtGui.QTextDocument(self)
def paint(self, painter, option, index):
painter.save()
self.initStyleOption(option, index)
self.doc.setHtml(option.text)
option_no_text = QtWidgets.QStyleOptionViewItem(option)
option_no_text.text = ''
style = QtWidgets.QApplication.style() if option_no_text.widget is None else option_no_text.widget.style()
style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, option_no_text, painter)
margin_top = (option.rect.height() - self.doc.size().height()) // 2
text_rect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, option_no_text, None)
text_rect.setTop(text_rect.top() + margin_top)
painter.translate(text_rect.topLeft())
painter.setClipRect(text_rect.translated(-text_rect.topLeft()))
context = QtGui.QAbstractTextDocumentLayout.PaintContext()
self.doc.documentLayout().draw(painter, context)
painter.restore()
def sizeHint(self, option, index):
other = super().sizeHint(option, index)
w = min(self.doc.idealWidth(), other.width())
h = max(self.doc.size().height(), other.height())
return QtCore.QSize(w, h)
class ExampleWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
item = QtGui.QStandardItem()
item.setText('Example<br><span style="font-size: 14pt; font-weight: bold;">Example<br>Example<br>Example</span>', )
model = QtGui.QStandardItemModel()
model.appendRow(item)
self.listview = QtWidgets.QListView(parent=self)
self.listview.setModel(model)
delegate = RichTextItemDelegate(self.listview)
self.listview.setItemDelegate(delegate)
app = QtWidgets.QApplication([])
example = ExampleWidget()
example.resize(320, 240)
example.show()
app.exec_()