I am adding a QGraphicTextItem to a scene using pyqt6. I cannot resize the widget border when text is resized. I have looked at a few way of resizing, but none work. The text does change to a bigger font via the context menu. The entire class is shown below.
class FreeTextGraphicsItem(QtWidgets.QGraphicsTextItem):
def __init__(self, x, y, text_):
super(FreeTextGraphicsItem, self).__init__(None)
self.x = x
self.y = y
self.text = text_
self.setFlags(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable |
QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsFocusable |
QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsSelectable)
self.font = QtGui.QFont(self.settings['font'], 9, QtGui.QFont.Weight.Normal)
self.setFont(self.font)
self.setPlainText(self.text)
self.setPos(self.x, self.y)
def contextMenuEvent(self, event):
menu = QtWidgets.QMenu()
menu.addAction(_("Large font"))
action = menu.exec(QtGui.QCursor.pos())
if action is None:
return
if action.text() == "Large font":
self.font = QtGui.QFont(self.settings['font'], 12, QtGui.QFont.Weight.Normal)
frame = self.document().documentLayout().frameBoundingRect(self.document().rootFrame())
self.boundingRect().setRect(0, 0, frame.width(), frame.height())
def paint(self, painter, option, widget):
color = QtCore.Qt.GlobalColor.white
painter.setBrush(QtGui.QBrush(color, style=QtCore.Qt.BrushStyle.SolidPattern))
painter.drawRect(self.boundingRect())
painter.setFont(self.font)
fm = painter.fontMetrics()
painter.setPen(QtGui.QColor(QtCore.Qt.GlobalColor.black))
lines = self.text.split('\\n')
for row in range(0, len(lines)):
painter.drawText(5, fm.height() * (row + 1), lines[row])
You're not using the features of QGraphicsTextItem.
In fact, you're completely ignoring and overriding most of its aspects:
x
and y
are existing and dynamic properties of all QGraphicsItems and should never be overwritten;font
of QGraphicsTextItem;setRect()
on the bounding rectangle is useless, as boundingRect()
is a *property getter" and is returned internally by the item based on its contents (in this case, the text set with setPlainText()
);If your main purpose is to draw a border around the item, then you should only do that, and then rely on the existing capabilities of the item.
class FreeTextGraphicsItem(QtWidgets.QGraphicsTextItem):
def __init__(self, x, y, text_):
super().__init__(text_.replace('\\n', '\n'))
self.setPos(x, y)
self.setFlags(
QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable
| QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsFocusable
| QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsSelectable
)
font = QtGui.QFont(self.settings['font'], 9, QtGui.QFont.Weight.Normal)
self.setFont(font)
self.setDefaulTextColor(QtGui.QColor(QtCore.Qt.GlobalColor.white))
def contextMenuEvent(self, event):
menu = QtWidgets.QMenu()
largeFontAction = menu.addAction(_("Large font"))
action = menu.exec(event.screenPos())
if action == largeFontAction:
font = QtGui.QFont(
self.settings['font'], 12, QtGui.QFont.Weight.Normal)
self.setFont(font)
def paint(self, painter, option, widget=None):
painter.save()
painter.setBrush(QtCore.Qt.GlobalColor.white)
painter.drawRect(self.boundingRect())
painter.restore()
super().paint(painter, option, widget)
Note: comparing actions with their text is pointless, other than conceptually wrong; not only you can have a more reliable object-based comparison using the action (as shown above), but that comparison can also become invalid: a menu could contain items that have the same names, and you're also probably using the _
for translations, so the text might not match at all.