python - 可点击的 SVG 图像运行方法
问题描述
我创建了一个需要交互的地图(火车)的 SVG 图像,当单击地图的一部分时,颜色会改变,并且会执行控制事物的方法(通过树莓派)。
将按钮连接到插槽很简单,我猜测我尝试过:
self.path.clicked.connect(self.some_func)
是否可以单击 SVG 元素并让它根据给定的方法执行方法,id
就像单击按钮时一样?
这是一个MVCE:
测试.svg
<svg height="100" width="100">
<circle id="elem1" cx="50" cy="50" r="40"/>
</svg>
svg_widget.py
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtXml import *
from PyQt5.QtSvg import *
import sys
class svgWidget(QSvgWidget):
def __init__(self, parent=None):
super(QSvgWidget, self).__init__(parent)
self.display = QTextEdit()
self.doc = QDomDocument("doc")
fName = QFile("test.svg")
if not fName.open(QIODevice.ReadOnly):
print("Cannot open the File")
exit(-1)
if not self.doc.setContent(fName):
print("Cannot parse the content")
fName.close()
exit(-1)
fName.close()
roots = self.doc.elementsByTagName("svg")
if roots.size() < 1:
print("Cannot find root")
exit(-1)
self.root = roots.at(0).toElement()
self.path = self.root.firstChild().toElement()
self.load(self.doc.toByteArray())
# self.path.clicked.connect(self.some_func)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
QTimer.singleShot(2000, lambda: self.some_func())
def some_func(self):
print('setting fill')
self.path.setAttribute("fill", "#44dd75")
print('setting stroke')
self.path.setAttribute("stroke", "#FF0000")
print('setting stroke-width')
self.path.setAttribute("stroke-width", "3")
self.load(self.doc.toByteArray())
self.execute_method()
def execute_method(self):
print('method executed')
if __name__ == "__main__":
app = QApplication(sys.argv)
svgWidget = svgWidget()
svgWidget.show()
sys.exit(app.exec_())
解决方案
我通过我的一个朋友找到了解决方案。
它是在 Stackoverflow 上找到的(他认为)。
如果有人知道出处,请编辑并添加链接以获得信用。
测试.svg
<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>
svg_mouse.py
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_())
推荐阅读
- python - 处理由 Python 中的 bin 表示的分类缺失值?
- c++ - 如何使用模板和 const 关键字处理指向类型?
- amazon-web-services - 不使用分区键查询 DynamoDB 表的全局二级索引
- python - django模型文件字段中的默认图像?
- javascript - 为什么使用 google oauath isSignedIn,listen()?
- python - 当子句卡住时,pyspark big
- python - 手动插入框架设置滚动条不起作用 tkinter
- javascript - 按内容查找 div
- reactjs - React - 找不到模块 - 好像目录不存在
- xamarin.forms - MonoAndroid90 的指定语言目标缺失。确保为“MonoAndroid”安装了正确的工具