(Pyqt:管理动态创建的自定义QWidget布局的最佳实践

时间:2012-11-13 13:04:23

标签: layout pyqt

我有一个QMainWindow有各种小部件,加载了loadUI。其中一个小部件是一个QGroupBox,它在开始时是空的(也没有布局)。 我还有一个自定义小部件(CustomWidgetContainer),它自己创建各种小部件(CustomWidget)。在运行时确定了多少和哪些。

问题是CustomWidgetContainer有自己的布局来添加其小部件。但是当CustomWidgetContainer被添加到QMainWindow时,布局将替换为QMainWindow的父级布局(这是预期的和记录的行为)。

但是当这个CustomWidgetContainer需要自己的布局(self.layout())来添加其他CustomWidgets或删除所有CustomWidgets时,self.layout()将返回None。

我可以想象所有类型的解决方法,检查父级是否已经有一个布局(使用那个,在父级中设置一个)等等。但我不想在我的孩子(CustomWidgetContainer)课程中对我的父母(QMainWindow)做任何事情,因为我认为这是一种不好的做法。

代码段:     ScalarInputEdit == CustomWidget,InputsWidget == CustomWidgetContainer

class MainWindow(qt.QMainWindow):
    ....
    def connect(self, host, port):
        self._client = PymotClient(host, port)
        self.client.connect()        
        self._set_enabled_connected()
        self.log.info("Connected to %s:%d", host, port)

        self._inputswidget = InputsWidget(self, self.client)
        print "Layout Before:", self._inputswidget.layout()
        self.inputsBox.setLayout(self._inputswidget.layout())
        print "Layout After:", self._inputswidget.layout()
        self._inputswidget.append_inputs_from_client()

class InputsWidget(qt.QWidget):
    def __init__(self, parent, client):
        super(InputsWidget, self).__init__(parent)
        ....
        self.setLayout(qt.QGridLayout())

    def append_inputs_from_client(self):
        for inp in some_list:
           self.append_input(inp)

    def append_input(self, pbo):
        self.layout().addWidget(ScalarInputEdit(self, self.client, pbo))

    def remove_all_inputs(self):
        for child in self.layout().children():
            child.deleteLater()

输出:

Layout Before: <PyQt4.QtGui.QGridLayout object at 0x8880ecc> 
Layout After: None
Exception: 
  File    "...inputwidgets.py", line 134, in append_input
    self.layout().addWidget(ScalarInputEdit(self, self.client, pbo))
AttributeError: 'NoneType' object has no attribute 'addWidget'

这样做的标准/良好做法是什么?对于我来说,在稍后阶段(__ init__之后)需要你的layout()似乎很常见。但是,由于某些用例似乎取代了我的布局,甚至更糟糕的是删除它,我如何确定要添加/删除的布局?

1 个答案:

答案 0 :(得分:0)

引用:

when the CustomWidgetContainer gets added to the QMainWindow, the layout is
replaced with the parenting layout of the QMainWindow (which is expected and
documented behaviour).

这对我来说非常不清楚:你指的是记录在案的行为?

self._inputswidget = InputsWidget(self, self.client)
print "Layout Before:", self._inputswidget.layout()
self.inputsBox.setLayout(self._inputswidget.layout())

为什么要将inputsBox的布局设置为_inputswidget的布局?

print "Layout After:", self._inputswidget.layout()

_inputswidget的布局现在很自然是None,因为您只是转移到inputsBox

self._inputswidget.append_inputs_from_client()

显然,这不起作用,因为你取消了_inputswidget的布局,并没有取代它。