Pyqt中的SVG字形

1 投票
1 回答
846 浏览
提问于 2025-04-16 03:56

我该如何在pyqt中使用svggraphicsItem来显示图形符号(glyphs)?

1 个回答

4

最近我发现用Cairo生成的svg文件在pyqt中显示不正常。这个问题是因为使用了glyphs(字形),而pyqt似乎无法显示这些字形(可能我理解错了,但我找不到让字形正常显示的方法)。

于是我写了一些函数,把字形转换成svg路径,这样文件就能正常显示了。

不过这些函数在渲染颜色和其他样式方面还有改进的空间(这些功能被锁定在我写的函数里)。

这些函数需要嵌入到一个类里,或者去掉self才能在其他地方使用。

我只是希望大家能有这些函数,这样就不用像我一样到处寻找在pyqt中渲染字形的方法了。

祝好运, Kyle

def convertSVG(self, file): 
    dom = self._getsvgdom(file) 
    print dom 
    self._switchGlyphsForPaths(dom) 
    self._commitSVG(file, dom) 
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): 
    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)

撰写回答