Menachem
Menachem

Reputation: 297

How to remove a widget in PYQT6 after it was added using a CheckBox

I am developing a Python GUI using PYQT6. The code below is a reduced version of my code that illustrates my problem. When the GUI comes up first time, I want to show an unchecked CheckBox widget, and below it a DateEdit widget. In addition, when I check the CheckBox, a LineEdit widget is added to the left of the DateEdit widget. So far the software works fine. However, when I uncheck the CheckBox to remove the LineEdit widget from the layout, the LineEdit widget continues to show in the layout. Any help is appreciated.

import  sys
from    PyQt6.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QCheckBox,
        QWidget, QHBoxLayout, QDateEdit, QLineEdit )
from    PyQt6 import QtCore
from    PyQt6.QtCore import QDate

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Example")
        global layout3 

        layout1 = QHBoxLayout()
        layout2 = QVBoxLayout()
        layout3 = QHBoxLayout()

        # Define the QCheckBox widget.
        self.CheckBox = QCheckBox("Enable Sales", self)
        self.CheckBox.toggled.connect(self.checkbox_toggled)
        
        # Define the QLineEdit widget
        self.item_entry = QLineEdit()
        self.item_entry.setPlaceholderText("Enter item")

        # Define the QDateEdit widget and set its date to the current date.
        self.date_entry = QDateEdit()
        self.date_entry.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
        self.date_entry.setCalendarPopup(True)
        self.date_entry.setEnabled(True)
        current_dated = QDate.currentDate()
        self.date_entry.setDate(current_dated)

        # Outline the layouts and add to them the CheckBox and the DateEdit widgets.
        # The QLineEdit widget will be added later dynamically.                                                
        layout1.addLayout(layout2)      
        layout2.addWidget(self.CheckBox, alignment=QtCore.Qt.AlignmentFlag.AlignCenter)
        layout2.addLayout(layout3)         
        layout3.addWidget(self.date_entry)
                 
        widget = QWidget()
        widget.setLayout(layout1)
        self.setCentralWidget(widget)       
    
    def checkbox_toggled(self):
        if self.CheckBox.isChecked() == True:
            layout3.addWidget(self.item_entry)   
            layout3.addWidget(self.date_entry)
        else:
            layout3.removeWidget(self.item_entry)
 
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

Upvotes: 1

Views: 941

Answers (1)

Alexander
Alexander

Reputation: 17344

One solution to this problem would be to delete the widget each time the checkbox becomes unchecked, and recreate it when it becomes checked. THis will completely remove it and allow the DateEdit Widget to grow and be totally visible.

For example:

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Example")
        layout1 = QHBoxLayout()
        layout2 = QVBoxLayout()
        self.layout3 = QHBoxLayout()
        self.CheckBox = QCheckBox("Enable Sales", self)
        self.CheckBox.toggled.connect(self.checkbox_toggled)
        self.date_entry = QDateEdit()
        self.date_entry.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
        self.date_entry.setCalendarPopup(True)
        self.date_entry.setEnabled(True)
        current_dated = QDate.currentDate()
        self.date_entry.setDate(current_dated)
        layout1.addLayout(layout2)
        layout2.addWidget(self.CheckBox, alignment=QtCore.Qt.AlignmentFlag.AlignCenter)
        layout2.addLayout(self.layout3)
        self.layout3.addWidget(self.date_entry)
        widget = QWidget()
        widget.setLayout(layout1)
        self.setCentralWidget(widget)

    def checkbox_toggled(self):
        if self.CheckBox.isChecked() == True:
            self.item_entry = QLineEdit()
            self.item_entry.setPlaceholderText("Enter item")
            self.layout3.addWidget(self.item_entry)
            self.layout3.addWidget(self.date_entry)
        else:
            i = self.layout3.indexOf(self.item_entry)
            self.layout3.takeAt(i)
            self.item_entry.deleteLater()

P.S. I turned the layout3 into an instance attribute so that you could access it in the checkbutton slot method without needing to make it a global variable. Changing it was for my own preference and it is not necessary for the solution to work.

Upvotes: 1

Related Questions