在使用 PyQt 构建应用程序时,有时需要在图形用户界面中渲染 SVG(可缩放矢量图形)文件,特别是当你需要显示图标或自定义字体时。QGraphicsSvgItem 是 PyQt 提供的一个类,用于在 QGraphicsViewQGraphicsScene 中渲染 SVG 图像。然而,如果你想使用 SVG 字形或通过编程方式生成矢量图形,QSvgRendererQGraphicsSvgItem 是两个关键的组件。

如何在Pyqt中渲染使用svggraphicsItem的SVG字形?_应用程序

1、问题背景

在 Pyqt 中使用 svggraphicsItem 渲染 SVG 字形时,可能会遇到一些问题。例如,由 Cairo 生成的 SVG 文件在 Pyqt 中无法正确显示,其中使用了 glyphs 图标,在 Pyqt 中似乎无法显示。

2、解决方案

为了解决此问题,提供了一个函数 convertSVG(self, file) 来将 glyphs 转换为 SVG 路径,以便文件能够正常渲染。此函数需要嵌入到类中或将 self 删除才能在其他地方使用。

def convertSVG(self, file):
    dom = self._getsvgdom(file)
    print(dom)
    self._switchGlyphsForPaths(dom)
    self._commitSVG(file, dom)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

以下是一些其他函数,用于在 Pyqt 中渲染 SVG 字形:

def _commitSVG(self, file, dom):
    f = open(file, 'w')
    dom.writexml(f)
    f.close()

def _getsvgdom(self, file):
    print('getting DOM model')
    import xml.dom
    import xml.dom.minidom as mini
    f = open(file, 'r')
    svg = f.read()
    f.close()
    dom = mini.parseString(svg)
    return dom

def _getGlyphPaths(self, dom):
    symbols = dom.getElementsByTagName('symbol')
    glyphPaths = {}
    for s in symbols:
        pathNode = [p for p in s.childNodes if 'tagName' in dir(p) and p.tagName == 'path']
        glyphPaths[s.getAttribute('id')] = pathNode[0].getAttribute('d')
    return glyphPaths

def _switchGlyphsForPaths(self, dom):
    glyphs = self._getGlyphPaths(dom)
    use = self._getUseTags(dom)
    for glyph in glyphs.keys():
        print(glyph)
        nl = self.makeNewList(glyphs[glyph].split(' '))
        u = self._matchUseGlyphs(use, glyph)
        for u2 in u:
            print(u2, 'brefore')
            self._convertUseToPath(u2, nl)
            print(u2, 'after')

def _getUseTags(self, dom):
    return dom.getElementsByTagName('use')

def _matchUseGlyphs(self, use, glyph):
    matches = []
    for i in use:
        print(i.getAttribute('xlink:href'))
        if i.getAttribute('xlink:href') == '#'+glyph:
            matches.append(i)
    print(matches)
    return matches

def _convertUseToPath(self, use, strokeD):
    ## strokeD is a list of lists of strokes to make the glyph
    newD = self.nltostring(self.resetStrokeD(strokeD, use.getAttribute('x'), use.getAttribute('y')))
    use.tagName = 'path'
    use.removeAttribute('xlink:href')
    use.removeAttribute('x')
    use.removeAttribute('y')
    use.setAttribute('style', 'fill: rgb(0%,0%,0%); stroke-width: 0.5; stroke-linecap: round; stroke-linejoin: round; stroke: rgb(0%,0%,0%); stroke-opacity: 1;stroke-miterlimit: 10; ')
    use.setAttribute('d', newD)

def makeNewList(self, inList):
    i = 0
    nt = []
    while i < len(inList):
        start = i + self.listFind(inList[i:], ['M', 'L', 'C', 'Z'])
        end = start + self.listFind(inList[start+1:], ['M', 'L', 'C', 'Z', '', ' '])
        nt.append(inList[start:end+1])
        i = end + 1
    return nt

def listFind(self, x, query):
    for i in range(len(x)):
        if x[i] in query:
            return i
    return len(x)

def resetStrokeD(self, strokeD, x, y):  # convert a list of strokes to xy coords
    nsd = []
    for i in strokeD:
        nsd.append(self.resetXY(i, x, y))
    return nsd

def resetXY(self, nl, x, y):  # convert a list of strokes to xy coords
    nl2 = []
    for i in range(len(nl)):
        if i == 0:
            nl2.append(nl[i])
        elif i%2:  # it's odd
            nl2.append(float(nl[i]) + float(x))
        elif not i%2:  # it's even
            nl2.append(float(nl[i]) + float(y))
        else:
            print(i, nl[i], 'error')
    return nl2

def nltostring(self, nl):  # convert a colection of nl's to a string
    col = []
    for l in nl:
        templ = []
        for c in l:
            templ.append(str(c))
        templ = ' '.join(templ)
        col.append(templ)
    return ' '.join(col)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.

通过以上方法,你可以在 PyQt 应用程序中成功渲染 SVG 字形,并通过图形视图与用户进行交互。