调整 qgraphicstextitem 的边框

Resize border of qgraphicstextitem

我正在使用 pyqt6 将 QGraphicTextItem 添加到场景中。 调整文本大小时,我无法调整小部件边框的大小。 我研究了几种调整大小的方法,但 none 行得通。 文本确实通过上下文菜单更改为更大的字体。 整个class如下图

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])

没有使用 QGraphicsTextItem 的功能。
事实上,您完全忽略并覆盖了它的大部分方面:

  • xy 是所有 QGraphicsItems 的现有和动态属性,永远不应被覆盖;
  • 与 QGraphicsTextItem 的 font 相同;
  • 在边界矩形上调用 setRect() 是无用的,因为 boundingRect() 是一个 *属性 getter" 并由项目根据其内容在内部返回(在本例中,文本设置为 setPlainText());
  • 文本绘制被完全覆盖,并且不可靠也不与项目的文本集一致,考虑到您正在用分割线绘制文本,而原始文本已经转义换行;

如果您的主要目的是在项目周围绘制边框,那么您应该只这样做,然后依赖项目的现有功能。

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)

注意:将动作与其文本进行比较是没有意义的,除了概念上的错误;使用操作(如上所示),您不仅可以获得更可靠的 object-based 比较,而且该比较也可能变得无效:菜单可能包含具有相同名称的项目,并且您也可能正在使用_ 用于翻译,因此文本可能根本不匹配。