Search code examples
pythonpyqtpyqt5qlayout

Dynamically add and remove a Layout when one of the Radio Button is Selected


I m able to dynamically add a layout to QHBoxLayout in pyqt , however I m unable to remove them once added.

Main aim is to dynamically add and remove a layout based on the Radio Button selected.

def SearchTab(self):

  self.layout = QVBoxLayout()

  button_layout = QHBoxLayout()
  radio_button_1 = QRadioButton("Search")
  radio_button_2 = QRadioButton("Update")
  button_layout.addWidget(radio_button_1)
  button_layout.addWidget(radio_button_2)
  self.layout.addItem(button_layout)

  radio_button_1.toggled.connect(lambda :self.SelectButtonCheck(radio_button_1))
  radio_button_1.toggled.connect(lambda :self.UpdateButtonCheck(radio_button_2))

  self.setTabText(0,"Search")

  self.tab1.setLayout(self.layout)


def SelectButtonCheck(self,b):
    if b.text() == "Search":
        if b.isChecked():
            print(b.text()+ "is selected")
            self.pg_details = pgd.PGDetails()
            layout = self.pg_details.returnLayout()
            self.layout.addLayout(layout)


def UpdateButtonCheck(self,b):

    if b.text() == "Update":
        if b.isChecked():
            print(b.text()+ " is selected")
            for i in  range(self.layout.count()):
                print(self.layout.itemAt(i))
                temp_layout = self.layout.itemAt(i)
                widget = temp_layout.widget()
                temp_layout.removeItem(temp_layout)

                if widget is not None:
                    widget.deleteLater()

Initial Screen-

Currently I m able to add the layout when "Search" Radio Button is selected --

Contains QFromLayout

But Nothing happens when I select "Update" RadioButton

Nothing Happens here and the application crashed

Also find the layouts that have been added-

for i in  range(self.layout.count()):
print(self.layout.itemAt(i))
<PyQt5.QtWidgets.QHBoxLayout object at 0x1180ec438>
<PyQt5.QtWidgets.QFormLayout object at 0x1180ff828>

Layouts are being added but not getting removed.

Any leads would be helpful , in what I m missing here


Solution

  • I was able to solve this. Took me a while but understood what is the arrangement of widgets within the layouts.

    I assumed removing the layout will cascade delete the widgets itself.

    I used the below function to remove the layout and its widgets corresponding to it.

    def SearchTab(self):
    
          self.layout = QVBoxLayout()
    
          button_layout = QHBoxLayout()
          radio_button_1 = QRadioButton("Search")
          radio_button_2 = QRadioButton("Update")
          button_layout.addWidget(radio_button_1)
          button_layout.addWidget(radio_button_2)
          self.layout.addItem(button_layout)
          #createDB()
          radio_button_1.toggled.connect(lambda :self.SelectButtonCheck(radio_button_1,self.layout))
          radio_button_1.toggled.connect(lambda :self.UpdateButtonCheck(radio_button_2,self.layout))
          #layout.addRow("Address",QLineEdit())
          self.setTabText(0,"Search")
    
          update_layout = QHBoxLayout()
          #update_layout.set
          #update_btn = QDialogButtonBox(QDialogButtonBox)
          #update_btn.setAlignment(Qt.AlignBottom)
          update_layout.setAlignment(QtCore.Qt.AlignTop)
          update_btn = QPushButton('Update')
          reset_btn = QPushButton('Reset')
          #self.layout.addRow(update_layout)
          update_layout.addWidget(update_btn)
          update_layout.addWidget(reset_btn)
    
          update_btn.clicked.connect(self.createDB)
    
          self.tab1.setLayout(self.layout)
    
        def SelectButtonCheck(self,b,stacklayout):
            if b.text() == "Search":
                if b.isChecked():
                    print(b.text()+ "is selected")
                    self.pg_details = pgd.PGDetails()
                    layout = self.pg_details.returnLayout()
                    self.layout.addLayout(layout)
    
        def removeLayout(self,layout):
                for i in  range(layout.count()):
                    temp_layout = layout.itemAt(i)
                    if temp_layout is not None:
                        widget = temp_layout.widget()
                        if widget is not None:
                            widget.deleteLater()
                    else:
                        return
                    if temp_layout.layout() is not None:
                        self.removeLayout(temp_layout.layout())
    
    
        def removeFormLayout(self,layout):
    
            if layout is not None:
    
                for i in  range(layout.count()):
                        temp_layout = layout.itemAt(i)
                        if isinstance(temp_layout.layout(),type(QFormLayout())):
                                self.removeLayout(temp_layout.layout())
    
                        else:
                            next
            else:
                return
    
    
        def UpdateButtonCheck(self,b,stacklayout):
    
            if b.text() == "Update":
                if b.isChecked():
                    print(b.text()+ " is selected")
                    self.removeFormLayout(stacklayout)
    

    The removeFormLayout function picks out the formlayout that I added with the Search radio button and removeLayout removes all the widgets under it as well.

    enter image description here

    Open to suggestions and improvements in the method used, I tried it with a couple of layout removals other then FormLayout as well. Currently it is working fine.

    Also is anybody aware of how to align the HBoxLayout at the top , the radio button starts from the middle again , I want to align them at the top of the screen