QGraphicsSVGItem的ItemClipsToShape未生效,如何实现形状贴合的选择框?
让QGraphicsSvgItem的选择框贴合SVG路径形状
你遇到的问题很典型:ItemClipsToShape这个标志的作用是裁剪图形超出自身形状的显示内容,而非改变选择区域的轮廓。QGraphicsSvgItem默认的选择区域是元素的边界矩形,要让选择框贴合SVG路径,需要重写它的shape()方法,返回对应路径的精确形状。
下面是具体的修改方案:
步骤1:重写shape()方法
我们需要从SVG渲染器中提取对应元素的路径,转换为QPainterPath并适配SVG中的变换,以此作为选择区域的形状。
首先在svg_mouse.py中补充必要的导入:
from PyQt5.QtGui import QPainterPath from PyQt5.QtCore import Qt
然后修改SvgItem类,添加shape()方法并开启选择功能:
class SvgItem(QGraphicsSvgItem): def __init__(self, id, renderer, parent=None): super().__init__(parent) self.id = id self.setSharedRenderer(renderer) self.setElementId(id) bounds = renderer.boundsOnElement(id) self.setPos(bounds.topLeft()) # 开启选择功能 self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True) # 若需要裁剪图形可保留此标志 self.setFlag(QtWidgets.QGraphicsItem.ItemClipsToShape, True) def shape(self): # 获取SVG元素的原始路径 path = self.renderer().pathForElement(self.id) # 适配SVG中的scale(0.1)变换 path = path.scaled(0.1, 0.1) # 对齐路径与元素的本地坐标系 bounds = self.renderer().boundsOnElement(self.id) path.translate(-bounds.topLeft()) return path # 保留原有鼠标事件方法 def mousePressEvent(self, event: 'QtWidgets.QGraphicsSceneMouseEvent'): print('svg item: ' + self.id + ' - mousePressEvent()') super().mousePressEvent(event) def mouseReleaseEvent(self, event: 'QtWidgets.QGraphicsSceneMouseEvent'): print('svg item: ' + self.id + ' - mouseReleaseEvent()') super().mouseReleaseEvent(event)
步骤2:原理说明
renderer().pathForElement(self.id):提取SVG元素对应的原始路径数据path.scaled(0.1, 0.1):匹配SVG中<g transform='scale(0.1)'>的缩放变换,确保形状与显示图形一致path.translate(-bounds.topLeft()):对齐路径原点与元素的本地坐标系,因为setPos(bounds.topLeft())已经调整了元素位置
测试效果
修改后运行代码,点击两个SVG元素,你会看到选择框完全贴合路径的轮廓,不再是原始的矩形框。
内容的提问来源于stack exchange,提问作者johnashu
相关产品推荐
相关产品推荐

