Inline svg als Hintergrund für QPushButton

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Kopakpy
User
Beiträge: 9
Registriert: Mittwoch 6. Dezember 2017, 22:19

Hallo liebe PyQtler,

Ich würde gerne inline svgs auf einen QPushButton dynamisch erzeugen.
Das ganze soll eine Library für ein LCARS ähnliches Interface werden.

Sowas wäre ganz toll:

Code: Alles auswählen

svg="""
<svg height="100" width="100">
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
"""    
self.notaus = QtGui.QPushButton(self.centralwidget)
self.notaus.setGeometry(QtCore.QRect(100,100, 100, 100))
self.notaus.setStyleSheet("border: none; \n background-image: " + self.foobar(svg) + ");\n")
Geht das irgendwie?
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Klappt es, wenn du einfach ein QLabel auf den Button setzt und dem Label dein Bild zuweist? Größe und Position könntest du dann ja vom Button übernehmen. Du müsstest nur noch zusätzlich reagieren, wenn der Button neugezeichnet werden muss, d.h. dass dein Label dann auch angepasst werden muss.

EDIT:
Wobei QIcon() doch an sich schon seit längerem SVG-Dateien verarbeiten kann. Führt das bei dir zu einer Fehlermeldung oder warum deine Frage?
Kopakpy
User
Beiträge: 9
Registriert: Mittwoch 6. Dezember 2017, 22:19

Alle Beispiele die ich finde, laden das SVG aus irgendwelchen Dateien. Ich möchte das SVG jedoch als String übergeben.
Kopakpy
User
Beiträge: 9
Registriert: Mittwoch 6. Dezember 2017, 22:19

Ich habe es jetzt wie folgt gelöst. Der Umweg über eine Datei gefällt mir zwar nicht sonderlich. Aber wenigstens funktioniert es.
Das lcars Projekt liegt auf github, und ist noch ganz am Anfang:
https://github.com/StowasserH/pylcars

Code: Alles auswählen

    def renderSvg(self,svg,size):
        if (type(size) is not QtCore.QSize):
            raise AttributeError("Pass QSize")
        renderer = QtSvg.QSvgRenderer(QtCore.QByteArray(svg))
        qim = QtGui.QImage(size, QtGui.QImage.Format_ARGB32)
        qim.fill(0)
        painter = QtGui.QPainter()
        painter.begin(qim)
        renderer.render(painter)
        painter.end()
        return qim
    
    def saveImg(self,svg,size):
        name=xxhash.xxh64(svg+str(size)).hexdigest()
        path=self.imageFolder + os.sep + name[:3]+ os.sep + name[3:6]+ os.sep 
        filename=name[6:]+".png"
        url=path+filename
        if(not os.path.isfile(url)):
          if( not os.path.isdir(path)):
            os.makedirs(path)
          image=self.renderSvg(svg,size)
          image.save(url,"PNG")
        return url
    
    def createButton(self,svg,size,text):
        if (type(size) is not QtCore.QSize):
            raise AttributeError("Pass QSize")
        button = QtGui.QPushButton(self.centralwidget)
        button.setFont(self.defaultFont)
        url=self.saveImg(svg,size)
        button.setStyleSheet( self.defaultStyle+"\nbackground-image: url("+url+");" )
        button.setText(_translate("MainWindow", text, None))
        button.setFlat(True)
        return button
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du solltest dich mal mit os.path.join vertraut machen, und mit string.format im allgemeinen. Damit verbessert sich die Lesbarkeit deutlich.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kopakpy: warum renderst Du jetzt das SVG in ein PNG und benutzt nicht das SVG direkt? Um temporäre Dateien zu erzeugen gibt es das Modul `tempfile`. Zum Code: eingerückt wird immer mit 4 Leerzeichen pro Ebene und nicht mal 4 und mal 2. `if` ist keine Funktion, die überflüssigen Klammern gehören weg. Um Pfade zusammenzusetzen nimmt man os.path.join. Zum Typvergleich nimmt man `isinstance` oder läßt die überflüssige Prüfung gleich ganz weg, Qt wird sich schon beschweren, wenn es mit `size` nichts anzufangen weiß. `AttributeError` ist dafür auch der falsche Fehler, hier würde es sich ja um einen TypeError handeln. Hast Du es schon mit setIcon versucht?
Kopakpy
User
Beiträge: 9
Registriert: Mittwoch 6. Dezember 2017, 22:19

Danke für den codereview. Ich werde ein paar Sachen ändern :-)
Wenns schon nicht im Speicher geht wollte ich die erzeugten Dateien dann auch gar nicht mehr temporär ablegen. So sind sie wenigstens gecached. Das ist auch der Grund warum ich PNGs exportiere.
Vor allem mit dem raspi ist es von Vorteil die Dateien auf der Speicherkarte zu lassen, und nicht immer wieder neu zu schreiben.
setIcon habe ich probiert, es hat auch soweit funktioniert. Allerdings ist das Icon dann nicht im Hintergrund d.H. ein setText überschreibt das Icon teilweise wieder.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Vielleicht ist für dich auch QML interessant. Das ist auch auf dem PI GPU beschleunigt.
Antworten