我为PyQt做了一个上下文管理器包装,其中__enter__
将设置布局或小部件,而__exit__
将其应用于父布局。基本上,它减少了创建布局所需的代码行,并且与缩进效果很好。
如果我想访问某些方法(例如remove_border
,如果它是QTreeWidget
),我将在小部件上使用包装器,但是我需要这样调用代码:
with MyClass(QtWidgets.QTreeWidget, parent_layout) as widget:
pass
是否有可能让我可以做widget = MyClass(QtWidgets.QTreeWidget, parent_layout)
,但仍然可以运行enter和exit方法?
编辑:基于code_onkel的答案,我分离了功能,但保持了相当简单,因此很多工作是自动完成的。
下面是一个QPushButton
的示例:
class Example(object):
...
def addQPushButton(self, *args, **kwargs):
with QWidgetPushButton(self, *args, **kwargs) as widget:
return widget
@contextmanager
def QPushButton(self, *args, **kwargs):
with QWidgetPushButton(self, *args, **kwargs) as widget:
yield widget
with Example(parent) as layout:
button_1 = layout.addQPushButton('1')
with layout.QPushButton('2') as button_2:
pass
答案 0 :(得分:0)
我认为解决此问题的最优雅的方法是稍微调整一下工厂模式,并添加包装函数以与工厂类进行交互。请参见下面的代码,其中有一个create_simple()
方法不是上下文管理器。恕我直言,这比在不需要上下文时强制执行上下文管理器要干净得多。如果您坚持使用单个工厂函数,则需要一个参数来告诉工厂是否要使用上下文管理器或简单的小部件(请参见create2()
)。
import contextlib
class WidgetFactory:
def __init__(self, widget_cls, parent=None):
self.widget_cls = widget_cls
self.widget = None
self.parent = parent
def create_widget(self):
# create widget
self.widget = object()
def setup_widget(self):
# do stuff
pass
def apply_to_parent(self):
# do suff
pass
@contextlib.contextmanager
def create(self):
self.create_widget()
self.setup_widget()
yield self.widget
self.apply_to_parent()
def create_simple(self):
self.create_widget()
self.setup_widget()
self.apply_to_parent()
return self.widget
def create(*args, **kwargs):
return WidgetFactory(*args, **kwargs).create()
def create_simple(*args, **kwargs):
return WidgetFactory(*args, **kwargs).create_simple()
def create2(*args, context=False, **kwargs):
factory = WidgetFactory(*args, **kwargs)
if context:
return factory.create()
else:
return factory.create_simple()
def main():
root = create_simple('dummy for qt class')
with create('dummy for qt class', root) as child:
# do stuff with child
print(child)
simple_child = create_simple('dummy for qt class', root)
print(simple_child)
if __name__ == '__main__':
main()