python - PyQt - 轻松将 QWidget 添加到所有视图
问题描述
我有以下
class MyView(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
layout = QVBoxLayout()
layout.addWidget(QLabel('Hello World'))
self.setLayout(layout)
class NavigationMenu(QWidget):
pass
# Renders a bar of full width and 15 px height
NavigationMenu
添加to的最简单方法是MyView
什么?
将来,我还必须将其添加NavigationMenu
到所有其他视图中,因此我正在寻找从打字和可维护性角度来看可扩展的东西。
我尝试了装饰器(就@NavigationMenuDecorator
在类的顶部),但我要么无法绑定它们,要么它们在解析时被初始化并出现错误QWidget: Must construct a QApplication before a QWidget
。
我尝试将它添加到 MyView 中,但有很多样板
class MyWidget(Widget.QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
layout = Widget.QVBoxLayout()
layout.addWidget(QLabel('Hello World'))
topLayout = Widget.QVBoxLayout()
topLayout.setContentsMargins(0, 0, 0, 0)
topLayout.addWidget(NavigationMenu())
topLayout.addLayout(layout)
self.setLayout(topLayout)
解决方案
一个可能的解决方案是使用元类:
from PyQt5 import QtCore, QtWidgets
class NavigationMenu(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(QtWidgets.QLabel("NavigationMenu"))
class MetaNavigationMenu(type(QtWidgets.QWidget), type):
def __call__(cls, *args, **kw):
obj = super().__call__(*args, **kw)
lay = obj.layout()
if lay is not None:
lay.addWidget(NavigationMenu())
return obj
class View(QtWidgets.QWidget, metaclass=MetaNavigationMenu):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(QtWidgets.QLabel('Hello World'))
self.setLayout(layout)
if __name__=="__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = View()
w.show()
sys.exit(app.exec_())
更新:
使用以下方法,您可以注入视图和视图所需的其他参数:
from PyQt5 import QtCore, QtWidgets
class NavigationMenu(QtWidgets.QWidget):
def __init__(self, value, text="", parent=None):
super().__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(QtWidgets.QLabel(text))
print(value)
class MetaMenu(type(QtWidgets.QWidget), type):
def __new__(cls, class_name, parents, attrs, **kwargs):
cls._view = kwargs.pop('view', None)
cls._args = kwargs.pop('args', tuple())
cls._kwargs = kwargs.pop('kwargs', dict())
return type.__new__(cls, class_name, parents, attrs)
def __call__(cls, *args, **kw):
obj = super().__call__(*args, **kw)
layout = getattr(obj, 'layout', None)
if callable(layout) and View is not None:
layout().addWidget(cls._view(*cls._args, **cls._kwargs))
return obj
class View(QtWidgets.QWidget, metaclass=MetaMenu, view=NavigationMenu, args=(10, ), kwargs={"text": "NavigationMenu"}):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(QtWidgets.QLabel('Hello World'))
self.setLayout(layout)
if __name__=="__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = View()
w.show()
sys.exit(app.exec_())
推荐阅读
- node.js - Mongoose findById 检查用户权限的正确方法
- html - 顶部和左侧不需要的空白
- javascript - JSON Stringfy 只有几个属性
- python - 从一个句子列表中删除一个点元素
- reactjs - Enter 和 Backspace 不能在 React 中使用 Slate.js 编辑器
- unity3d - 如果我要求奖励视频太多会不会有问题?
- regex - RegEx 用于匹配从 0.00 到 50.00 的数字
- python - Cython 不适用于带参数的双装饰器。有解决方法吗?
- scala - 如何将文件列中的值列表解析为Spark sql Dataframe
- sql - 如何在特殊规则下连接列?