[英]Using PyQt5/Pyside2 to set a repeating SVG pattern as main window/Qwidget background
I've generated the SVG css code through http://www.heropatterns.com/ and I'm trying to use it as the background for my main window/Qwidget.我已经通过http://www.heropatterns.com/生成了 SVG css 代码,我试图将它用作我的主窗口/Qwidget 的背景。 I want the background to resize as the window grows bigger or shrinks.我希望背景随着窗口变大或缩小而调整大小。 I tried calling Form.setStyleSheet() with the generated css being passed in as an argument, but I only get the one of the two colors(the backround color) in the pattern.我尝试调用 Form.setStyleSheet() 并将生成的 css 作为参数传入,但我只得到模式中的两种颜色之一(背景颜色)。 What's the proper way to display a SVG as the backround of the main QWidget window and see the complete pattern?将 SVG 显示为 QWidget 主窗口的背景并查看完整模式的正确方法是什么? I know QSvgRenderer exists, however, I'm not sure once I create the QSvgRenderer object where I go from there to make the SVG a resizable background.我知道QSvgRenderer存在,但是,一旦我创建了 QSvgRenderer 对象,我就不确定从那里开始使 SVG 成为可调整大小的背景。 I was told to use background-repeat: repeat;
我被告知使用background-repeat: repeat;
property in the style sheet, however, that didn't change anything.但是,样式表中的属性并没有改变任何东西。
Here's the Minimal, Complete, and Verifiable example I wrote:这是我写的最小、完整和可验证的示例:
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 300)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.horizontalLayout_2.addLayout(self.horizontalLayout)
self.retranslateUi(Form)
Form.setStyleSheet("""background-repeat: repeat; background-color: #000000;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='hexagons' fill='%23b0b0b0' fill-opacity='0.4' fill-rule='nonzero'%3E%3Cpath d='M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");""")
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
How the form currently Looks:表单当前的外观:
How the form should look:表单的外观:
XML representation of SVG pattern SVG 模式的 XML 表示
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="49" viewBox="0 0 28 49"><g fill-rule="evenodd"><g id="hexagons" fill="#000" fill-rule="nonzero"><path d="M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z"/></g></g></svg>
Example of button background being changed:更改按钮背景的示例:
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 300)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.horizontalLayout_2.addLayout(self.horizontalLayout)
self.Start_Stop_button = QtWidgets.QPushButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.Start_Stop_button.sizePolicy().hasHeightForWidth())
self.Start_Stop_button.setSizePolicy(sizePolicy)
self.Start_Stop_button.setMinimumSize(QtCore.QSize(0, 0))
self.Start_Stop_button.setBaseSize(QtCore.QSize(0, 0))
self.Start_Stop_button.setIconSize(QtCore.QSize(16, 16))
self.Start_Stop_button.setFlat(False)
self.Start_Stop_button.setObjectName("Start_Stop_button")
contents = b"<svg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'><g fill-rule='evenodd'><g id='hexagons' fill='#b0b0b0' fill-opacity='0.4' fill-rule='nonzero'><path d='M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z'/></g></g></svg>"
file = QtCore.QTemporaryFile(Form)
if file.open():
file.write(contents)
file.flush()
Form.setStyleSheet("""background-color: #000000;
background-image: url(%s);""" % file.fileName())
#Form.show()
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1))
self.Start_Stop_button.setText(QtWidgets.QApplication.translate("Form", "Start", None, -1))
class Widget(QtWidgets.QWidget, Ui_Form):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.setupUi(self)
def paintEvent(self, event):
opt = QtWidgets.QStyleOption()
opt.init(self)
painter = QtGui.QPainter(self)
self.style().drawPrimitive(QtWidgets.QStyle.PE_Widget, opt, painter, self)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
QSS does not support this type of url, a workaround is to save the content in a temporary file that is deleted when the application is closed, for this we use QTemporaryFile. QSS 不支持这种类型的 url,解决方法是将内容保存在应用程序关闭时删除的临时文件中,为此我们使用 QTemporaryFile。
On the other the url has the following format: data:image/svg+xml,<CONTENT>
, that is the content you should use.另一方面,url 具有以下格式: data:image/svg+xml,<CONTENT>
,这是您应该使用的内容。
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 300)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.horizontalLayout_2.addLayout(self.horizontalLayout)
self.retranslateUi(Form)
contents = b"<svg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'><g fill-rule='evenodd'><g id='hexagons' fill='#b0b0b0' fill-opacity='0.4' fill-rule='nonzero'><path d='M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z'/></g></g></svg>"
file = QtCore.QTemporaryFile(Form)
if file.open():
file.write(contents)
file.flush()
Form.setStyleSheet("""background-color: #000000;
background-image: url(%s);""" % file.fileName())
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
It seems that PySide2
is a bit special, and it looks more like Qt since this problem was waiting for it in C ++ but not in Python.看起来PySide2
有点特别,看起来更像Qt,因为这个问题在C++中等待它而不是在Python中。 For a widget to support QSS
should be implemented paintEvent
using QStyle
but for this we must create the class widget since the class Ui_Form
is not a widget, it is just a class that serves to fill the widget.对于支持QSS
的小部件,应该使用QStyle
实现paintEvent
但为此我们必须创建类小部件,因为类Ui_Form
不是小部件,它只是一个用于填充小部件的类。 Below I show the workable code.下面我展示了可行的代码。
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 300)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.horizontalLayout_2.addLayout(self.horizontalLayout)
self.retranslateUi(Form)
contents = b"<svg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'><g fill-rule='evenodd'><g id='hexagons' fill='#b0b0b0' fill-opacity='0.4' fill-rule='nonzero'><path d='M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z'/></g></g></svg>"
file = QtCore.QTemporaryFile(Form)
if file.open():
file.write(contents)
file.flush()
Form.setStyleSheet("""background-color: #000000;
background-image: url(%s);""" % file.fileName())
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1))
class Widget(QtWidgets.QWidget, Ui_Form):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.setupUi(self)
def paintEvent(self, event):
opt = QtWidgets.QStyleOption()
opt.init(self)
painter = QtGui.QPainter(self)
self.style().drawPrimitive(QtWidgets.QStyle.PE_Widget, opt, painter, self)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
Plus:加:
QSS has rules to apply the styles that are indicated in the following links: QSS 具有应用以下链接中指示的样式的规则:
In your case so that it only applies to the current widget you must use the objectName
:在您的情况下,它仅适用于当前小部件,您必须使用objectName
:
Form.setStyleSheet("""QWidget#Form{background-color: #000000;
background-image: url(%s);}""" % file.fileName())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.