Problem
I want a convenient way to create a widget that has a QHBoxLayout or QVBoxLayout as its layout. The type of the widget is not known initially and is only supplied later on.
Usage
As a class decorator
This is happens to be the part of the code that keeps getting repeated.
# 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)
# 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)
As a callable
If I can use it as a callable that returns an instance of a specific widget that will be a plus. Then I will not necessarily need to create a subclass each time I wish to use a convenient container widget.
# Conveniently create a button box
# without having to write a subclass
btnBox = BoxedWidget(QFrame, Qt.Horizontal)
btnBox.addtoLayout(QPushbutton("OK"))
btnBox.addtoLayout(QPushbutton("Cancel")
Possible Solutions
From the research that I've done it seems the following solutions may solve the problem.
Override __new__: I really do not understand the mechanism and behind the scenes work of the __new__
method despite all the blog posts I've read. I mean I do not understand enough to even ask the right questions.
Use a metaclass: I'm not really sure about this
Create a factory function*: Create a BoxedMainWindow
, BoxedDialog
, BoxedFrame
subclasses of BoxedWidget. The factory function then decides from the parameters which type to use in the creation of the instance.
Create a decorator class/function: I understand decorators a bit. This is what I hacked together and needless to say it is failing.
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 layoutWidget(self, widget, *args, **kwargs):
layout = self.widgetInstance.layout()
layout.addWidget(widget, *args, **kwargs)
return BoxedWidget
The error message: AttributeError: 'functools.partial' object has no attribute 'layoutWidget'
I am open to all solutions though I prefer the fourth one. Any help is appreciated.
Aucun commentaire:
Enregistrer un commentaire