【问题标题】:How to position and anchor text in a QGraphicsScene?如何在 QGraphicsScene 中定位和锚定文本?
【发布时间】:2020-06-26 23:51:03
【问题描述】:

所以我有这个小代码sn-p:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

from PyQt5 import (QtWidgets as qtw, QtCore as qtc, QtGui as qtg)
import qdarkstyle
style = qdarkstyle.load_stylesheet_pyqt5()

class Scene(qtw.QGraphicsScene):
    """
    contains data
    """

    gridSize = (10, 10)
    rectSize = 30

    def __init__(self, parent, ):

        super(Scene, self).__init__(parent)
        self.setSceneRect(0, 0, 600, 400)
        self.createGrid(*self.gridSize)

    def createGrid(self, height, width):
        rectSize = self.rectSize

        self.fields = [
                [self.addRect(
                    rectSize*(1+x), rectSize*(1+y), rectSize, rectSize)
                 for x in range(width)]
                for y in range(height)]

        self.column_ids = [
                self.addText(letter) for letter in
                [chr(65 + i) for i in range(self.gridSize[1])]]
        [x.setPos(rectSize*(1.5 + i), rectSize*.5)
         for i, x in enumerate(self.column_ids)]

        self.row_ids = [
                self.addText(letter) for letter in
                [str(i) for i in range(1, self.gridSize[0])]]
        [x.setPos(rectSize*.5, rectSize*(1.5+i))
         for i, x in enumerate(self.row_ids)]


class View(qtw.QGraphicsView):
    """
    displays data
    """

    def __init__(self, parent=None, scene=None):

        super(View, self).__init__(parent)

        self.setScene(Scene(self))
        self.setMouseTracking(True)


if __name__ == '__main__':
    app = qtw.QApplication(sys.argv)
    app.setStyleSheet(style)
    widget = qtw.QWidget()
    playerView = View(widget)
    widget.setGeometry(300, 300, 400, 300)
    widget.show()

    sys.exit(app.exec_())

它创建一个 QGraphicScene,添加一些矩形,使它们形成一个网格,然后写入一些文本来标识网格的行和列。

当我设置 row_id 和 column_id 的位置时,它似乎是文本边界框左上角的位置。

我想要的是文本框的中心与网格的行/列中矩形的中心对齐。

即结果应如下所示:

___|_A_|_B_|_C_|_D_|_E_|___
   |   |   |   |   |   |
 1 |   |   |   |   |   |
___|___|___|___|___|___|___
   |   |   |   |   |   |
 2 |   |   |   |   |   |
___|___|___|___|___|___|___

但我现在得到的更像是这样的:

___|__A|__B|__C|__D|__E|___
   |   |   |   |   |   |
   |   |   |   |   |   |
__1|___|___|___|___|___|___
   |   |   |   |   |   |
   |   |   |   |   |   |
__3|___|___|___|___|___|___

我搜索了 QGraphicsScene.addText 和 QTextItem 的文档,以找到一种将 setPos 方法的锚点设置为 center 或类似的方法,但找不到任何东西。

我可能只获取文本项的边界框的大小并减去一半的位置以获得正确的结果,但这似乎是一个 hack,我更愿意直接定位 TextItems 的中心。

【问题讨论】:

    标签: python pyqt pyqt5


    【解决方案1】:

    通过减去中心来设置文本项的位置并不是一种技巧,它是唯一(或至少是最简单的)解决方案。

    如文档所示,该项目始终使用为左上角设置的坐标定位,就像 all QGraphicsItems(实际上是所有 QWidgets)一样。

    因此,定位它们的正确方法是从要放置项目的位置减去 boundingRect 中心。我建议您避免像以前那样使用列表推导:没有性能优势,而且会降低代码的可读性。

        self.column_ids = []
        for i in range(self.gridSize[1]):
            letter = chr(65 + i)
            pos = qtc.QPointF(rectSize * (1.5 + i), rectSize * .5)
            item = self.addText(letter)
            item.setPos(pos - item.boundingRect().center())
            self.column_ids.append(item)
    
        self.row_ids = []
        for i in range(self.gridSize[0]):
            pos = qtc.QPointF(rectSize * .5, rectSize * (1.5 + i))
            item = self.addText(str(i + 1))
            item.setPos(pos - item.boundingRect().center())
            self.row_ids.append(item)
    

    考虑一下,您还可以创建 QGraphicsTextItem 的子类并覆盖其 setPos 方法,或者(更好地)创建自己的居中方法。

    class CenteredTextItem(qtw.QGraphicsTextItem):
        def centerAt(self, pos):
            self.setPos(pos - self.boundingRect().center())
    
    class Scene(qtw.QGraphicsScene):
        def createGrid(self, height, width):
            # ...
            for i in range(self.gridSize[1]):
                letter = chr(65 + i)
                pos = qtc.QPointF(rectSize * (1.5 + i), rectSize * .5)
                item = CenteredTextItem(letter)
                self.addItem(item)
                item.centerAt(pos)
                self.column_ids.append(item)
    
            self.row_ids = []
            for i in range(self.gridSize[0]):
                pos = qtc.QPointF(rectSize * .5, rectSize * (1.5 + i))
                item = CenteredTextItem(str(i + 1))
                self.addItem(item)
                item.centerAt(pos)
                self.row_ids.append(item)
    

    【讨论】:

      猜你喜欢
      • 2020-02-03
      • 1970-01-01
      • 2020-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多