Layout (Py)Qt:管理定制QWidget'的最佳实践;动态创建的布局

Layout (Py)Qt:管理定制QWidget'的最佳实践;动态创建的布局,layout,pyqt,Layout,Pyqt,我有一个QMainWindow,其中包含各种小部件,加载了loadUI。其中一个小部件是QGroupBox,它在开始时是空的(也没有布局)。 我还有一个自定义小部件(CustomWidgetContainer),它在自己内部创建各种小部件(CustomWidget)。运行时确定多少和哪些 问题是CustomWidgetContainer有自己的布局可添加其小部件。但是,当CustomWidgetContainer添加到QMainWindow时,该布局将被替换为QMainWindow的父级布局(这

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

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

但是,当这个CustomWidgetContainer需要自己的布局(self.layout())来添加其他CustomWidget或删除所有CustomWidget时,self.layout()将不返回任何内容

我可以想象各种各样的变通方法,检查父级是否已经有布局(使用该布局,在父级中设置一个布局等)。但是我不想和我的孩子(CustomWidgetContainer)班做任何事情,因为我认为这个坏的练习。 片段: 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'
之前的布局:
布局后:无
例外情况:
文件“…inputwidgets.py”,第134行,在append\u输入中
self.layout().addWidget(ScalarInputEdit(self,self.client,pbo))
AttributeError:“非类型”对象没有属性“addWidget”
这样做的标准/良好实践是什么?对于我来说,在以后的某个阶段(在_uuu\init\uuu之后)需要您的布局()似乎很常见。但是,由于某些用例似乎取代了我的布局,或者更糟的是将其删除,我如何确定要添加/删除到/从中删除的布局?

Quote:

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
的布局设置为
\u inputswidget
的布局

print "Layout After:", self._inputswidget.layout()
\u inputswidget
的布局现在很自然地变成了
None
,因为您刚刚将它转移到了
inputsBox

self._inputswidget.append_inputs_from_client()

显然,这是行不通的,因为你拿走了
\u inputswidget
的布局,而没有替换它。

我所指的有文档记录的行为是:“如果布局是另一个小部件上的布局管理器,setLayout()将重新分配布局,并使其成为这个小部件的布局管理器。”我现在明白为什么要替换它了(因为我使用setLayout)。但是我还有什么其他方法可以让我的InputsWidget成为_inputsBox的内容呢?或者,一般来说,做这件事的“最佳实践”是什么?我花了很多时间试图让它以不同的方式工作。大部分结果都是未渲染的InputsWidget(纯灰色_inputsBox)@中间类
InputsWidget
的用途是什么?为什么不直接委托给
inputsBox
,或者直接使用一个函数向其中添加小部件?目的是让InputsWidget绘制一个复合小部件(几个编辑框和一些旋钮f.e.)没有实际的边框。然后调用方将决定呈现小部件的布局。但是,唯一有效的解决方案是让inputsBox成为InputsWidget的一部分。因此InputsWidget有一个带有小部件的布局。该布局被分配给一个groupbox。然后在groupbox周围添加一个“一次性”布局。groupbox的边框可以这是一种解决方法,但很有效。它看起来有点难看,我仍然对其他人是如何做到这一点感兴趣。