tisaconundrum
tisaconundrum

Reputation: 2292

QT: How can I dynamically add and delete widgets in a layout?

def add_ranges(self):
    self.ranges_layout = QtGui.QHBoxLayout()                            # setup the ranges_layout, it will be a child of all_ranges_layout
    self.min_label = QtGui.QLabel(self.normalization)                   # setup the min label
    self.max_label = QtGui.QLabel(self.normalization)                   # setup the max label
    self.min_lineEdit = QtGui.QLineEdit(self.normalization)             # setup the min lineEdit
    self.max_lineEdit = QtGui.QLineEdit(self.normalization)             # setup the max lineEdit
    self.all_ranges_layout.addLayout(self.ranges_layout)                # make ranges_layout a child of all_ranges_layout
    self.ranges_layout.addWidget(self.min_label)                        # apply the min label to the widget
    self.ranges_layout.addWidget(self.min_lineEdit)                     # apply the min lineEdit to the widget
    self.ranges_layout.addWidget(self.max_label)                        # apply the max label
    self.ranges_layout.addWidget(self.max_lineEdit)                     # apply the max lineEdit
    self.min_label.setText(_translate("MainWindow", "Min", None))       # set the text of the min label
    self.max_label.setText(_translate("MainWindow", "Max", None))       # set the text of the max label

    self.min_lineEdits.append(self.min_lineEdit)                        # set up an array of lineEdits
    self.max_lineEdits.append(self.max_lineEdit)                        #

def del_ranges(self):
    self.ranges_layout.removeWidget(self.min_label)                     # remove the min label to the widget
    self.ranges_layout.removeWidget(self.min_lineEdit)                  # remove the min lineEdit to the widget
    self.ranges_layout.removeWidget(self.max_label)                     # remove the max label
    self.ranges_layout.removeWidget(self.max_lineEdit)                  # remove the max lineEdit
    del self.min_lineEdits[-1]                                          # delete last element in list
    del self.max_lineEdits[-1]                                          # delete last element in list

enter image description here Click on "Add Ranges", two new boxes appear for the user to add data into.

enter image description here Click on "Delete Ranges", nothing happens except the buttons visually move up. This tells me that the function is working (sort of) and is deleting the layout, but not not the lineEdits and labels.

These are two functions from a program that I'm designing. I want to have widgets added and removed with the press of a button. I tried using deleteLater() however, this function was also falling into the same pit; not actually deleting the lineEdits and labels. Is it a problem of not disconnecting before deleting?

Upvotes: 1

Views: 3016

Answers (1)

tisaconundrum
tisaconundrum

Reputation: 2292

Here is a method that can be used to iteratively go through the layout and deleteLater() each widget within the specific layout. in this case self.all_ranges_layout

Code

def del_ranges(self):
    to_delete = self.all_ranges_layout.takeAt(self.all_ranges_layout.count() - 1)
    if to_delete is not None:
        while to_delete.count():
            item = to_delete.takeAt(0)
            widget = item.widget()
            if widget is not None:
                widget.deleteLater()
            else:
                pass

Plain English

get the layout item at n-1 index
if there are any objects to be deleted
    while the count of objects is not 0
        get the layout item at 0th index
        get the widget at this location
        if there is an object in this widget
            deleteLater this widget

Upvotes: 2

Related Questions