创建仅在创建超类时才知道的子类

时间:2018-08-21 12:53:47

标签: python design-patterns pyqt decorator factory

问题

我想要一种方便的方法来创建具有QHBoxLayout或QVBoxLayout作为其布局的小部件。小部件的类型可以是最初未知但在创建时指定的任何容器小部件。

用法

作为班级装饰者

我正在重复很多与此类似的代码。即。创建布局并将其设置为父窗口小部件的布局,然后再添加项目。

# Insted of this
class JukeBox(QDialog):
    PLAYING, STOPPED, PAUSED = range(3)
    def __init__(self, *args, **kwargs):
        super(JukeBox, self).__init__(self, *args, **kwargs)
        self.state = STOPPED
        self.mainLayout = QVBoxLayout()
        self.playBtn = QPushbutton("Play")
        self.mainLayout.addWidget(self.playBtn)
        self.setLayout(self.mainLayout)

# I want to write this
@BoxWidget(QDialog, Qt.Vertical)
class JukeBox:
    PLAYING, STOPPED, PAUSED = range(3)
    def __init__(self, *args, **kwargs):
        self.state = JukeBox.STOPPED
        self.playBtn = QButton("Play")
        self.layout().addWidget(self.playBtn)

可致电

如果我可以将其用作可回调函数,则返回一个特定小部件的实例,该实例将为加号。这样,每次使用方便的容器小部件时,就不必创建子类。

# Conveniently create a button box
# without having to write a subclass
btnBox = BoxedWidget(QFrame, Qt.Horizontal)
btnBox.addtoLayout(QPushbutton("OK"))
btnBox.addtoLayout(QPushbutton("Cancel")

可能的解决方案

根据我所做的研究,似乎以下解决方案可以解决问题。

覆盖__new __ :尽管我已经阅读了所有博客文章,但我真的不了解__new__方法的机制和幕后工作。我的意思是我不甚了解,甚至无法提出正确的问题。

使用元类:我不确定该解决方案是否可行,但像__new__一样,我并不真正理解该机制

创建工厂功能:创建BoxedWidget的BoxedMainWindowBoxedDialogBoxedFrame子类。然后,工厂函数根据参数确定在实例创建中使用哪种类型。我可能必须重写各个子类中的某些部分,而其他解决方案可以消除对这些部分的需求

创建装饰器类/功能:我对装饰器有些了解。这就是我共同努力的结果,不用说它失败了。

def boxedWidget(Cls, orient=Qt.Horizontal):

    @functools.wraps
    class BoxedWidget:
        def __init__(self, *args, **kwargs):
            self.widgetInstance = Cls(*args, **kwargs)
            layout = QHBoxLayout()
            if orient == Qt.Vertical:
                layout = QVBoxLayout()
            self.widgetInstance.setLayout(layout)

        def addtoLayout(self, widget, *args, **kwargs):
            layout = self.widgetInstance.layout()
            layout.addWidget(widget, *args, **kwargs)

    return BoxedWidget

错误消息:AttributeError: 'functools.partial' object has no attribute 'layoutWidget'

尽管我喜欢第四个解决方案,但我对所有解决方案都持开放态度。任何帮助表示赞赏。

0 个答案:

没有答案