Seite 1 von 1

Inline svg als Hintergrund für QPushButton

Verfasst: Mittwoch 6. Dezember 2017, 22:42
von Kopakpy
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?

Re: Inline svg als Hintergrund für QPushButton

Verfasst: Mittwoch 6. Dezember 2017, 23:21
von snafu
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?

Re: Inline svg als Hintergrund für QPushButton

Verfasst: Donnerstag 7. Dezember 2017, 00:21
von Kopakpy
Alle Beispiele die ich finde, laden das SVG aus irgendwelchen Dateien. Ich möchte das SVG jedoch als String übergeben.

Re: Inline svg als Hintergrund für QPushButton

Verfasst: Samstag 9. Dezember 2017, 02:44
von Kopakpy
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

Re: Inline svg als Hintergrund für QPushButton

Verfasst: Samstag 9. Dezember 2017, 09:19
von __deets__
Du solltest dich mal mit os.path.join vertraut machen, und mit string.format im allgemeinen. Damit verbessert sich die Lesbarkeit deutlich.

Re: Inline svg als Hintergrund für QPushButton

Verfasst: Samstag 9. Dezember 2017, 11:20
von Sirius3
@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?

Re: Inline svg als Hintergrund für QPushButton

Verfasst: Samstag 9. Dezember 2017, 13:56
von Kopakpy
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.

Re: Inline svg als Hintergrund für QPushButton

Verfasst: Samstag 9. Dezember 2017, 14:04
von __deets__
Vielleicht ist für dich auch QML interessant. Das ist auch auf dem PI GPU beschleunigt.