我正在子类QGraphicsItem
化以创建一个地图标记,该标记绘制一个图标(基于多边形点的常量字典)和一个文本标签。
下面的boundingRect
方法定义了一个固定的边界框矩形。但由于文本标签可以是任意长度,我需要每个标记实例的边界框不同(例如,用于选择和聚焦)。
如何根据字符在屏幕上占据的实际像素宽度获取每个标记实例的边界矩形?我是否需要根据字体大小和字符数手动估算?或者 Qt 可以自动计算吗?
import sys
from PySide6 import QtCore, QtWidgets
from PySide6.QtWidgets import (
QApplication, QWidget, QHBoxLayout, QVBoxLayout,
QGraphicsScene, QGraphicsView, QGraphicsItem
)
from PySide6.QtGui import QColor, QFont, QPen, QBrush, QPolygon
from PySide6.QtCore import QPointF, Qt, QRectF, QPoint
MARKERS = {
'peak': {'color': 'limegreen', 'shape': 'star'},
'tag': {'color': 'bisque', 'shape': 'x'},
'pole': {'color': 'coral', 'shape': 'circle'}
}
SHAPES = {
'star': [(-1, -1), (0, -5), (1, -1), (5, 4), (0, 1), (-5, 4), (-1, -1)],
'x': [(0, -2), (3, -5), (5, -3), (2, 0), (5, 3),
(3, 5), (0, 2), (-3, 5), (-5, 3), (-2, 0), (-5, -3), (-3, -5)]
}
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('Map')
self.scene = MapScene()
self.view = QGraphicsView(self.scene)
# Main layout
layout = QHBoxLayout()
layout.addWidget(self.view)
self.setLayout(layout)
class MapMarker(QGraphicsItem):
def __init__(self, marker, label):
super().__init__()
self.marker = marker
self.label = label
# Build QPolygon dictionary from SHAPES coordinates
self.shapes = {}
for k, v in SHAPES.items():
self.shapes[k] = QPolygon([QPoint(*point)for point in SHAPES[k]])
# Set marker color
self.color = QColor(MARKERS[self.marker]['color'])
def paint(self, painter, option, widget):
brush = QBrush(Qt.SolidPattern)
brush.setColor(self.color)
painter.setPen(QPen(self.color))
painter.setBrush(brush)
# Draw marker shape
shape_name = MARKERS[self.marker]['shape']
if shape_name == 'circle':
painter.drawEllipse(-4, -4, 8, 8)
else:
painter.drawPolygon(self.shapes[shape_name])
# Draw marker label
painter.drawText(10, -2, self.label)
def boundingRect(self):
return QRectF(-10, -15, 200, 30)
class MapScene(QGraphicsScene):
def __init__(self):
super().__init__()
markers = [
(10, 10, 'peak', 'Some peak'),
(20, 30, 'tag', 'Some tag with a longer name'),
]
# Draw markers
for x, y, m, b in markers:
marker = MapMarker(m, b)
marker.setPos(x, y)
self.addItem(marker)
if __name__ == '__main__':
app = QApplication([])
widget = MainWindow()
widget.show()
sys.exit(app.exec())