如何解决PyQt5如何将不同的QStyle应用于不同的小部件?
我试图用QStyleFactory提供的内置样式制作具有不同样式的多个小部件,但是当我运行代码时,它们看起来都一样。我该如何解决?
from PyQt5 import QtWidgets,QtCore,QtGui
import sys
class Demo(QtWidgets.QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
self.container = QtWidgets.QWidget()
self.setCentralWidget(self.container)
self.layout = QtWidgets.QVBoxLayout()
self.container.setLayout(self.layout)
self.btn = QtWidgets.QPushButton("button")
self.lw = QtWidgets.QListWidget()
self.lw.addItems(["one","two","three"])
self.layout.addWidget(self.btn)
self.layout.addWidget(self.lw)
self.resize(400,150)
self.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
widgets = []
for style_name in QtWidgets.QStyleFactory.keys():
demo = Demo()
demo.setWindowTitle(style_name)
style = QtWidgets.QStyleFactory.create(style_name)
demo.setStyle(style)
widgets.append(demo)
sys.exit(app.exec_())
解决方法
QWidget.setStyle()
文档中报告了在 widgets 上设置QStyle(而不是在整个应用程序上设置)的重要方面:
设置小部件的样式不会影响现有或将来的子小部件。
因此,正在发生的事情是,您仅在QMainWindow上设置样式, ,而子级将始终使用QApplication样式。
您可以尝试做的是手动设置现有子项的样式:
for style_name in QtWidgets.QStyleFactory.keys():
demo = Demo()
demo.setWindowTitle(style_name)
style = QtWidgets.QStyleFactory.create(style_name)
demo.setStyle(style)
for child in demo.findChildren(QtWidgets.QWidget):
child.setStyle(style)
widgets.append(demo)
无论如何,上述方法都有一个缺点:设置样式后创建的任何新子代仍将继承 QApplication 样式。避免这种情况的唯一方法是通过(递归地)在父级上安装事件过滤器来监视childEvent()
,并相应地设置样式。请注意,您还需要注意StyleChange
个事件。
class ChildEventWatcher(QtCore.QObject):
def __init__(self,parentWidget):
super().__init__()
self.parentWidget = parentWidget
self.parentWidget.installEventFilter(self)
def eventFilter(self,source,event):
if event.type() == QtCore.QEvent.ChildAdded and isinstance(event.child(),QtWidgets.QWidget):
event.child().installEventFilter(self)
event.child().setStyle(self.parentWidget.style())
for child in event.child().findChildren(QtWidgets.QWidget):
child.installEventFilter(self)
child.setStyle(self.parentWidget.style())
elif event.type() == QtCore.QEvent.StyleChange and source == self.parentWidget:
for child in self.parentWidget.findChildren(QtWidgets.QWidget):
child.setStyle(self.parentWidget.style())
return super().eventFilter(source,event)
class Demo(QtWidgets.QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
# this *must* be created before adding *any* child
self.childEventWatcher = ChildEventWatcher(self)
# ...
还请记住文档警告的另一个重要方面:
警告:此功能对于演示目的特别有用,您可以在其中演示Qt的样式功能。实际的应用程序应避免使用它,而应使用一种一致的GUI样式。
虽然上面的代码可以完成您的期望,但是在 all 子QWidgets上安装事件过滤器并不是一件好事,尤其是在您只需要更改样式的情况下(通常应该只在程序开始时执行一次)。考虑到有关使用不同样式的警告,我强烈建议您按照建议的方式进行操作:出于演示目的,仅。
,您可以在应用程序上进行设置。
from PyQt5 import QtWidgets,QtCore,QtGui
import sys
class Demo(QtWidgets.QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
self.container = QtWidgets.QWidget()
self.setCentralWidget(self.container)
self.layout = QtWidgets.QVBoxLayout()
self.container.setLayout(self.layout)
self.btn = QtWidgets.QPushButton("button")
self.lw = QtWidgets.QListWidget()
self.lw.addItems(["one","two","three"])
self.layout.addWidget(self.btn)
self.layout.addWidget(self.lw)
self.resize(400,150)
self.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
win = Demo()
app.setStyle(QtWidgets.QStyleFactory.create("Windows")) # Set style theme on app
sys.exit(app.exec_())
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。