Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

option in QStyledItemDelegate.paint not updating



  • I am writing a messenger in PyQt5. I use QListView with QStyledItemDelegate to draw the messages. This is the code for my class:

    class MessageDelegate(QStyledItemDelegate):
        font = 0
    
        def __init__(self, font, *args, **kwargs):
            super(MessageDelegate, self).__init__(*args, **kwargs)
            self.font = font
    
        def paint(self, painter, option, index):
            text = index.model().data(index, Qt.DisplayRole)
            field = QRect(option.rect)
            field = field.marginsRemoved(Defines.TEXT_PADDING)
            doc = QTextDocument(text)
            doc.setDocumentMargin(0)
            opt = QTextOption()
            opt.setWrapMode(opt.WrapAtWordBoundaryOrAnywhere)
            doc.setDefaultTextOption(opt)
            doc.setDefaultFont(self.font)
            doc.setTextWidth(field.size().width() - 20)
            field.setHeight(int(doc.size().height()))
            field.setWidth(int(doc.idealWidth()))
            field = field.marginsAdded(Defines.TEXT_PADDING)
            rect = QRect(option.rect.right() - field.size().width() - 20, option.rect.y(), field.size().width(), field.size().height())
            bubblerect = rect.marginsRemoved(Defines.BUBBLE_PADDING)
            textrect = rect.marginsRemoved(Defines.TEXT_PADDING)
            painter.setPen(Qt.cyan)
            painter.setBrush(Qt.cyan)
            painter.drawRoundedRect(bubblerect, 10, 10)
            p1 = bubblerect.topRight()
            painter.drawPolygon(p1 + QPoint(-20, 0), p1 + QPoint(20, 0), p1 + QPoint(0, 15))
            painter.setPen(Qt.black)
            painter.setFont(self.font)
            painter.translate(textrect.x(), textrect.y())
            textrectf = QRectF(textrect)
            textrectf.moveTo(0, 0)
            doc.drawContents(painter, textrectf)
            painter.translate(-textrect.x(), -textrect.y())
    
        def sizeHint(self, option, index):
            global window_width
            print(option.rect)
            text = index.model().data(index, Qt.DisplayRole)
            field = QRect(option.rect)
            field.setWidth(window_width - 30)
            field = field.marginsRemoved(Defines.TEXT_PADDING)
            doc = QTextDocument(text)
            doc.setDocumentMargin(0)
            opt = QTextOption()
            opt.setWrapMode(opt.WrapAtWordBoundaryOrAnywhere)
            doc.setDefaultTextOption(opt)
            doc.setDefaultFont(self.font)
            doc.setTextWidth(field.size().width() - 20)
            field.setHeight(int(doc.size().height()))
            field.setWidth(int(doc.idealWidth()))
            field = field.marginsAdded(Defines.TEXT_PADDING)
            return QSize(0, field.size().height())
    

    I don't know how to calculate height in sizeHint properly, so I am using current window width as global variable. It is wierd, but it works, so nevermind.
    The problem is that when I have two messages and I narrow down the height of the first one grows (as it takes more lines), and hence the second message should go down. I printed option.rect that I get in paint. At first the Y coordinate for the second message is accurate and equals the height of the first message. However, as the window is narrowed down, the height of the first message grows, but the Y coordinate of option.rect in paint is not updating. Therefore, the messages are painted over each other. The size in sizeHint is calculated correctly, i printed the value to test that.
    Why does this happen and how can I solve this issue?


Log in to reply