I am writing an application in PyQt and I need to wrap the text that I am painting. I use boundingRect
method of QFontMetrics
class to define the size and then QPainter.drawText
to draw. I need the text to fit in a given rectangle. This is the line I use:
rect = metrics.boundingRect(rect, Qt.TextWordWrap, text)
However, due to the flag Qt.TextWordWrap
, if the text doesn't have any spaces it doesn't wrap and will not fit in the rectangle. I tried Qt.TextWrapAnywhere
but this breaks the words apart even when there are spaces. The Qt.TextFlag
doesn't seem to have any flag, that prioritize wrapping words and only if it is impossible, breaks the words apart, like QTextOption.WrapAtWordBoundaryOrAnywhere
.
Is there a way to wrap text like this using boundingRect
and drawText
?
For situations like these, it's usually better to use a QTextDocument, which allows using more advanced options.
class WrapAnywhereLabel(QtWidgets.QWidget):
def __init__(self, text=''):
super().__init__()
self.doc = QtGui.QTextDocument(text)
self.doc.setDocumentMargin(0)
opt = QtGui.QTextOption()
opt.setWrapMode(opt.WrapAtWordBoundaryOrAnywhere)
self.doc.setDefaultTextOption(opt)
def hasHeightForWidth(self):
return True
def heightForWidth(self, width):
self.doc.setTextWidth(width)
return self.doc.size().height()
def sizeHint(self):
return self.doc.size().toSize()
def resizeEvent(self, event):
self.doc.setTextWidth(self.width())
def paintEvent(self, event):
qp = QtGui.QPainter(self)
self.doc.drawContents(qp, QtCore.QRectF(self.rect()))
import sys
app = QtWidgets.QApplication(sys.argv)
w = WrapAnywhereLabel('hellooooo hello hellooooooooooooooo')
w.show()
sys.exit(app.exec_())