You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让QGraphicsTextItem同时居中于QGraphicsScene并支持自动换行?

QGraphicsTextItem 居中与自动换行兼容解决方案

问题现象

无法让QGraphicsTextItem同时在QGraphicsScene中居中且支持自动换行:

  • 注释掉self._text.document().adjustSize():文本能随窗口大小自动换行,但无法居中,位置随机
  • 保留该代码:文本居中,但换行效果固定,不会适配场景尺寸

问题根源

  1. adjustSize()会强制文档收缩到内容的最小尺寸,导致文本宽度被锁定,无法随窗口调整换行
  2. 原代码中sceneRect未与viewport同步,居中计算的基准错误,导致位置偏移

解决方法

  1. 窗口 resize 时同步sceneRect与viewport尺寸,确保居中计算的基准正确
  2. 依赖QTextDocument自身的尺寸计算(设置textWidth后,文档会自动计算高度),直接用文档的实际尺寸计算居中位置,无需调用adjustSize()

修改后的完整代码

import sys
from PySide6.QtCore import Qt, QRectF
from PySide6.QtGui import QColor, QFont
from PySide6.QtWidgets import (
    QApplication,
    QGraphicsView,
    QGraphicsScene,
    QGraphicsTextItem,
    QGraphicsPixmapItem,
    QVBoxLayout,
    QWidget,
)


class ImageViewer(QGraphicsView):
    def __init__(self, text="", parent=None):
        super().__init__(parent)

        self._scene = QGraphicsScene(self)
        self._photo = QGraphicsPixmapItem()
        self._photo.setShapeMode(QGraphicsPixmapItem.ShapeMode.BoundingRectShape)
        self._scene.addItem(self._photo)

        self._text = QGraphicsTextItem(text)
        self._text.setDefaultTextColor(QColor(255, 255, 255))
        font = QFont()
        font.setPointSize(20)
        self._text.setFont(font)
        self._scene.addItem(self._text)

        self.setScene(self._scene)
        self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
        self.setResizeAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.setBackgroundBrush(QColor(0, 0, 0))
        self.setFrameShape(QGraphicsView.Shape.NoFrame)

        self._center_text()

    def _center_text(self):
        # 同步sceneRect与viewport尺寸
        viewport_rect = self.viewport().rect()
        self._scene.setSceneRect(viewport_rect)
        
        max_width = viewport_rect.width() - 20
        self._text.document().setTextWidth(max_width)
        
        # 获取文档的实际尺寸
        doc_size = self._text.document().size()
        scene_rect = self._scene.sceneRect()
        
        # 计算居中位置
        center_x = scene_rect.center().x() - doc_size.width() / 2
        center_y = scene_rect.center().y() - doc_size.height() / 2
        self._text.setPos(center_x, center_y)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self._center_text()


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        layout = QVBoxLayout(self)
        self.viewer = ImageViewer(
            "This is a centered text. Resize to test the wrapping behavior."
        )
        layout.addWidget(self.viewer)
        self.setLayout(layout)
        self.setWindowTitle("QGraphicsTextItem Example")
        self.resize(800, 600)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

关键修改点

  • 在_center_text中添加self._scene.setSceneRect(viewport_rect),确保scene的范围和视图一致
  • 使用self._text.document().size()获取文本的实际宽高,替代boundingRect(),避免尺寸计算偏差
  • 移除adjustSize()调用,让文档能根据textWidth自动调整换行和高度

内容的提问来源于stack exchange,提问作者Valeria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 11:42:07