pyside - how to delete widgets from gridLayout

别说谁变了你拦得住时间么 提交于 2019-12-02 01:39:40

The problem here is caused by an implementation detail of QGridLayout.

Whenever items are deleted from a QGridLayout, the number of logical rows and columns will never decrease, even though the number of visual rows or colums may do. Because of this, you should always work directly with the items in the QGridLayout using methods such as getItemPosition and itemAtPosition.

Below is a re-write of the DesignerMainWindow class from the example using this approach. Obviously, it may need tweaking somewhat to work with your real application.

class DesignerMainWindow(QtGui.QMainWindow, Ui_fiberModesMainWindow):
    def __init__(self, parent = None):
        super(DesignerMainWindow, self).__init__(parent)
        self.setupUi(self)
        self.pb_addRow_1.clicked.connect( self.addRow )

    def addRow( self ):
        rows = self.PropertyLayout.rowCount()
        columns = self.PropertyLayout.columnCount()
        for column in range(columns):
            layout = self.PropertyLayout.itemAtPosition(rows - 1, column)
            if layout is not None:
                widget = layout.widget()
                if isinstance(widget, QtGui.QPushButton):
                    widget.setText('Remove %d' % (rows - 1))
                    widget.clicked.disconnect(self.addRow)
                    widget.clicked.connect(self.removeRow)
                else:
                    widget.setEnabled(False)
        widget = QtGui.QLineEdit(self.centralwidget)
        self.PropertyLayout.addWidget(widget, rows, 1, 1, 1)
        widget = QtGui.QPushButton(self.centralwidget)
        widget.setText('Add Row')
        widget.clicked.connect(self.addRow)
        self.PropertyLayout.addWidget(widget, rows, columns - 1, 1, 1)

    def removeRow(self):
        index = self.PropertyLayout.indexOf(self.sender())
        row = self.PropertyLayout.getItemPosition(index)[0]
        for column in range(self.PropertyLayout.columnCount()):
            layout = self.PropertyLayout.itemAtPosition(row, column)
            if layout is not None:
                layout.widget().deleteLater()
                self.PropertyLayout.removeItem(layout)

It looks like you didn't call QGridLayout::removeWidget() for all cells in row that you would like to remove. Then due to PySide the layout will keep referencing to the widgets and they are not really removed/deleted when you call setParent(None).

Also when you try deleteLater() of widget in the cell without QLayout::removeWidget(), then the cell will be not removed but stay alive (there is QLayoutItem will be left in the cell)

three_pineapples

EDIT: This doesn't solve the problem, also I found the source of my knowledge: Is there any way to remove a QWidget in a QGridLayout?

-- For some reason, removing widgets from layouts is hard. I spent a long time searching for the answer once, and no longer remember where I found it, but I digress...

What you need to do is the following. First find the item you want to remove. You can use layout.itemAt() or layout.itemAtPosition to get a reference to it.

Now, to remove the item from the layout, simply call item.widget().setParent(None). This will have the effect of removing the item from the layout!

Note: If you already have a reference to the widget, you can probably just call setParent on it without having to find it from the layout. I haven't tried that though (but don't see why it wouldn't work).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!