Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python ItemClipsToShape QGraphicsSVGItem_Python_Svg_Pyqt_Pyqt5_Qgraphicssvgitem - Fatal编程技术网

Python ItemClipsToShape QGraphicsSVGItem

Python ItemClipsToShape QGraphicsSVGItem,python,svg,pyqt,pyqt5,qgraphicssvgitem,Python,Svg,Pyqt,Pyqt5,Qgraphicssvgitem,以下标志不起作用,因此无法剪裁形状。而是创建一个矩形选择 self.setFlag(self.ItemClipsToShape) 如何将选择剪辑设置为形状 test.svg svg_mouse.py 从PyQt5导入QtWidgets 从PyQt5.QtSvg导入QGraphicsSvgItem、qsvgrender SvgItem类(QGraphicsSvgItem): def u uu init uuuuu(self,id,renderer,parent=None): super()

以下标志不起作用,因此无法剪裁形状。而是创建一个矩形选择

self.setFlag(self.ItemClipsToShape)

如何将选择剪辑设置为形状

test.svg


svg_mouse.py

从PyQt5导入QtWidgets
从PyQt5.QtSvg导入QGraphicsSvgItem、qsvgrender
SvgItem类(QGraphicsSvgItem):
def u uu init uuuuu(self,id,renderer,parent=None):
super()。\uuuu init\uuuu(父级)
self.id=id
self.setSharedRenderer(渲染器)
self.setElementId(id)
bounds=渲染器。boundsOnElement(id)
self.setPos(bounds.topLeft())
#self.setFlag(qtwidts.QGraphicsItem.ItemIsSelectable,True)#选择框
def mousePressEvent(self,事件:“qtwidts.qgraphicscscenemouseevent”):
打印('svg项:'+self.id+'-mousePressEvent()'))
super().mousePressEvent(事件)
def mouseReleaseEvent(self,event:'QtWidgets.QGraphicsSceneMouseEvent'):
打印('svg项:'+self.id+'-mouseReleaseEvent()'))
super().mouseReleaseEvent(事件)
SvgViewer类(qtwidts.QGraphicsView):
定义初始化(自身,父级):
super()。\uuuu init\uuuu(父级)
self.\u scene=qtwidts.qgraphicscene(self)
self.\u renderer=qsvgrender()
self.setScene(self.\u场景)
def set_svg(自身、数据):
self.resetTransform()
self._scene.clear()
self.\u renderer.load(数据)
item1=SvgItem('p2',self.\u渲染器)
自我._场景.附加项(第1项)
item2=SvgItem('p3',自渲染器)
自我._场景.附加项(第2项)
def mousePressEvent(self,事件:“qtwidts.qgraphicscscenemouseevent”):
打印('SvgViewer-mousePressEvent()'))
super().mousePressEvent(事件)
def mouseReleaseEvent(self,event:'QtWidgets.QGraphicsSceneMouseEvent'):
打印('SvgViewer-mousereleasevent()'))
super().mouseReleaseEvent(事件)
类窗口(qtwidts.QWidget):
定义初始化(自):
super()。\uuuu init\uuuuu()
self.viewer=SvgViewer(self)
vb_layout=qtwidts.QVBoxLayout(self)
vb_layout.addWidget(self.viewer)
img=b''
'''
self.viewer.set_svg(img)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
导入系统
app=qtwidts.QApplication(sys.argv)
window=window()
窗口设置几何体(500300600400)
window.show()
sys.exit(app.exec_())

我认为QGraphicsSvgItem使用边界矩形作为其形状

一个可能的老套但有效的解决方案是像QGraphicsPixmapItem那样,获取掩码并使用alpha区域返回元素的
shape()

请注意,我没有设置ItemClipsToShape标志,因为不需要它。
我还实现了正确的选择大纲,基于


我认为QGraphicsSvgItem使用边界矩形作为其形状

一个可能的老套但有效的解决方案是像QGraphicsPixmapItem那样,获取掩码并使用alpha区域返回元素的
shape()

请注意,我没有设置ItemClipsToShape标志,因为不需要它。
我还实现了正确的选择大纲,基于


实际上我做了你的测试,现在我不知道你的意思。您的意思是选择矩形不遵循实际的项目路径吗?我认为这与剪辑无关。要获得自定义的高亮度选择,您需要重新实现
paint()
方法并自己绘制高亮度。还重新实现了
QGraphicsItem::shape()
,但我不确定这是否会影响选择框。实际上,我运行了您的测试,现在我不确定您的意思。您的意思是选择矩形不遵循实际的项目路径吗?我认为这与剪辑无关。要获得自定义的高亮度选择,您需要重新实现
paint()
方法并自己绘制高亮度。还有重新实现的
QGraphicsItem::shape()
,尽管我不确定这会影响选择框。啊,来自QImage的掩码,好主意!虽然不幸的是,我恐怕选择的仍然是
boundingRect()
。然后点击链接到
qt\u graphicsItem\u highlightSelected
,不幸的是,它没有使用
shape()
(我不知道为什么,因为它已经是一个QPainterPath了,所以绘制它似乎同样容易!)。因此需要重新实现
paint()
和高亮绘制例程(但是一旦知道
形状
就相当容易了)。嗯,我明白你的意思了……但是,实际上它是将选择框剪裁到形状上,选择没有跟随形状。细微的差别,但留下了渲染瑕疵。试着设置
self.setFlag(qtwidts.QGraphicsItem.ItemIsMovable,True)
然后将下拉框移到更大的区域上……我认为这会更明显。当然,这可能是可以接受的。另外,图像形状遮罩似乎在圆边周围造成了一些“锯齿”……而不是抗锯齿。如果给形状加上颜色和轮廓(如实际MRE代码上方发布的SVG代码中),效果会更明显.好的,我明白了。我忘了ItemClipsToShape在非垂直/水平线上的表现不是很好,因为绘制剪裁没有抗锯齿,而且实际上我们也不需要该标志。我也用选择更新了示例。感谢您指出这一点!啊,来自QImage的掩码,好主意!但不幸的是,选择仍然会存在恐怕是
boundingRect()
了。然后点击链接到
qt\u graphicsItem\u highlightSelected
,不幸的是它没有使用
shape()
(我不知道为什么,看起来它和e一样。)
<svg viewBox='0 0 108 95' 
xmlns='http://www.w3.org/2000/svg'>
<g transform='scale(0.1)'>
        <path id="p2" fill='blue' stroke='red' d='M249,699v43h211v-43h-64l-2,3l-2,4l-4,3c0,0-1,2-2,2h-4c-2,0-3,0-4,1c-1,1-3,1-3,
                        2l-3,4c0,1-1,2-2,2h-4c0,0-2,1-3,0l-3-1c-1,0-3-1-3-2c-1-1,0-2-1-3l-1-3c-1-1-2-1-3-1c-1,0-4,
                        0-4-1c0-2,0-3-1-4v-3v-3z'/>
    <path id="p3" fill='blue' d='M385,593c0,9-6,15-13,15c-7,0-13-6-13-15c0-8,12-39,14-39c1,0,12,31,12,39'/>
</g>
</svg>
from PyQt5 import QtWidgets
from PyQt5.QtSvg import QGraphicsSvgItem, QSvgRenderer

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) #horrible selection-box

    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)

class SvgViewer(QtWidgets.QGraphicsView):
    def __init__(self, parent):
        super().__init__(parent)
        self._scene = QtWidgets.QGraphicsScene(self)
        self._renderer = QSvgRenderer()
        self.setScene(self._scene)

    def set_svg(self, data):
        self.resetTransform()
        self._scene.clear()
        self._renderer.load(data)
        item1 = SvgItem('p2', self._renderer)
        self._scene.addItem(item1)
        item2 = SvgItem('p3', self._renderer)
        self._scene.addItem(item2)

    def mousePressEvent(self, event: 'QtWidgets.QGraphicsSceneMouseEvent'):
        print('SvgViewer - mousePressEvent()')
        super().mousePressEvent(event)

    def mouseReleaseEvent(self, event: 'QtWidgets.QGraphicsSceneMouseEvent'):
        print('SvgViewer - mouseReleaseEvent()')
        super().mouseReleaseEvent(event)

class Window(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.viewer = SvgViewer(self)
        vb_layout = QtWidgets.QVBoxLayout(self)
        vb_layout.addWidget(self.viewer)
        img = b'''
                <svg viewBox='0 0 108 95' xmlns='http://www.w3.org/2000/svg'>
                    <g transform='scale(0.1)'>
                        <a href=""><path id="p2" d='M249,699v43h211v-43h-64l-2,3l-2,4l-4,3c0,0-1,2-2,2h-4c-2,0-3,0-4,1c-1,1-3,1-3,
                            2l-3,4c0,1-1,2-2,2h-4c0,0-2,1-3,0l-3-1c-1,0-3-1-3-2c-1-1,0-2-1-3l-1-3c-1-1-2-1-3-1c-1,0-4,
                            0-4-1c0-2,0-3-1-4v-3v-3z'/></a>
                        <path id="p3" d='M385,593c0,9-6,15-13,15c-7,0-13-6-13-15c0-8,12-39,14-39c1,0,12,31,12,39'/>
                    </g>
                </svg>'''
        self.viewer.set_svg(img)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 300, 600, 400)
    window.show()
    sys.exit(app.exec_())
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)


        # create an image based on the item size
        img = QtGui.QImage(bounds.size().toSize(), QtGui.QImage.Format_ARGB32)
        # clear its buffer (this is important!)
        img.fill(QtCore.Qt.transparent)
        # create a qpainter and ask the renderer to render it
        qp = QtGui.QPainter(img)
        renderer.render(qp, id)
        qp.end()

        # create the mask by adding a QRegion based on it
        mask = img.createAlphaMask()
        shape = QtGui.QPainterPath()
        shape.addRegion(QtGui.QRegion(QtGui.QBitmap.fromImage(mask)))
        # a QBitmap based region can be unnecessarily complex, let's
        # simplify it
        self._shape = shape.simplified()

    def shape(self):
        return self._shape

    def paint(self, qp, option, widget):
        # keep track of the selected state and call the base painting
        # implementation without it
        selected = option.state & QtWidgets.QStyle.State_Selected
        option.state &= ~QtWidgets.QStyle.State_Selected
        super().paint(qp, option, widget)

        if selected:
            # draw the selection based on the shape, using the right
            # amount of contrast with the background
            fgcolor = option.palette.windowText().color()
            bgcolor = QtGui.QColor(
                0 if fgcolor.red() > 127 else 255, 
                0 if fgcolor.green() > 127 else 255, 
                0 if fgcolor.blue() > 127 else 255, 
            )

            qp.setPen(QtGui.QPen(bgcolor, 0, QtCore.Qt.SolidLine))
            qp.setBrush(QtCore.Qt.NoBrush)
            qp.drawPath(self._shape)

            qp.setPen(QtGui.QPen(option.palette.windowText(), 0, QtCore.Qt.DashLine))
            qp.setBrush(QtCore.Qt.NoBrush)
            qp.drawPath(self._shape)