python-如何在布局中间插入QWidgets?

我正在使用Qt框架来构建图形用户界面.我使用QGridLayout整齐地放置我的QWidgets.
GUI如下所示:

python-如何在布局中间插入QWidgets?

我的应用程序会在运行时定期将新的小部件添加到GUI.这些新的小部件通常不添加在QLayout的末尾,而是添加在中间的某个位置.

这样做的过程有点麻烦.应用于上图,我需要从QGridLayout中取出widg_C,widg_D,….接下来,我添加widg_x和widg_y,最后再将其他小部件放回去.
这就是我从QGridLayout中删除小部件的方法:

for i in reversed(range(myGridLayout.count())):
    self.itemAt(i).widget().setParent(None)
###

只要您处理少量的小部件,此过程就不会造成灾难.但是在我的应用程序中,我显示了很多小部件-可能有50个或更多!在此过程进行期间,应用程序冻结了一秒钟,这对用户来说非常烦人.
有没有一种方法可以在QLayout中的某个位置插入小部件,而无需取出其他小部件?

编辑:显然,QVBoxLayout的解决方案非常简单.只需使用函数insertWidget(..)而不是addWidget(..).可以通过以下链接找到文档:http://doc.qt.io/qt-5/qboxlayout.html#insertWidget
不幸的是,我找不到QGridLayout的类似功能.

编辑:许多人正确地提到,放回许多小部件不应该导致性能问题-确实非常快(感谢@ekhumoro指出这一点).显然,我遇到的性能问题与将小部件放回原处的算法有关.这是一个相当复杂的递归算法,它将每个小部件放在QGridLayout中的正确坐标上.这导致显示器上出现“闪烁”.小部件被取出,并由于某种算法而延迟放回内部-导致闪烁.

编辑:我找到了一个解决方案,使我可以轻松地将新行插入QGridLayout.插入新行意味着我不需要从头开始取出并替换所有小部件-因此,我避免了运行昂贵的递归算法.
该解决方案可以在下面的我的答案中找到.

解决方法:

谢谢@ ekhumoro,@ Stuart Fisher,@ vahancho和@mbjoe的帮助.我最终找到了解决问题的方法.我不再使用QGridLayout().相反,我围绕QVBoxLayout构建了一个包装器,使其表现得好像是GridLayout,并带有一个额外的功能来插入新行:

class CustomGridLayout(QVBoxLayout):
    def __init__(self):
        super(CustomGridLayout, self).__init__()
        self.setAlignment(Qt.AlignTop)  # !!!
        self.setSpacing(20)


    def addWidget(self, widget, row, col):
        # 1. How many horizontal layouts (rows) are present?
        horLaysNr = self.count()

        # 2. Add rows if necessary
        if row < horLaysNr:
            pass
        else:
            while row >= horLaysNr:
                lyt = QHBoxLayout()
                lyt.setAlignment(Qt.AlignLeft)
                self.addLayout(lyt)
                horLaysNr = self.count()
            ###
        ###

        # 3. Insert the widget at specified column
        self.itemAt(row).insertWidget(col, widget)

    ''''''

    def insertRow(self, row):
        lyt = QHBoxLayout()
        lyt.setAlignment(Qt.AlignLeft)
        self.insertLayout(row, lyt)

    ''''''

    def deleteRow(self, row):
        for j in reversed(range(self.itemAt(row).count())):
            self.itemAt(row).itemAt(j).widget().setParent(None)
        ###
        self.itemAt(row).setParent(None)

    def clear(self):
        for i in reversed(range(self.count())):
            for j in reversed(range(self.itemAt(i).count())):
                self.itemAt(i).itemAt(j).widget().setParent(None)
            ###
        ###
        for i in reversed(range(self.count())):
            self.itemAt(i).setParent(None)
        ###

    ''''''
上一篇:python-PyQt QSpinBox更新范围取决于其他Spinbox的值


下一篇:在Python中返回具有角色的对象,并在QML中获取另一个对象的引用