如何让QGraphicsTextItem同时居中于QGraphicsScene并支持自动换行?
QGraphicsTextItem 居中与自动换行兼容解决方案
问题现象
无法让QGraphicsTextItem同时在QGraphicsScene中居中且支持自动换行:
- 注释掉
self._text.document().adjustSize():文本能随窗口大小自动换行,但无法居中,位置随机 - 保留该代码:文本居中,但换行效果固定,不会适配场景尺寸
问题根源
adjustSize()会强制文档收缩到内容的最小尺寸,导致文本宽度被锁定,无法随窗口调整换行- 原代码中
sceneRect未与viewport同步,居中计算的基准错误,导致位置偏移
解决方法
- 窗口 resize 时同步
sceneRect与viewport尺寸,确保居中计算的基准正确 - 依赖
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
相关产品推荐
相关产品推荐

