简体   繁体   English

删除 PyQt5 中的小部件时如何删除黑色空间

[英]How to remove black space when deleting widgets in PyQt5

I have a code to generate a GUI with PyQt5 that enables a user to create multiple buttons (QPushButton) based on an entry (QLineEdit), and to delete these buttons when pressing an "X" button (deleteLater()).我有一个代码可以使用 PyQt5 生成 GUI,它使用户能够基于条目 (QLineEdit) 创建多个按钮 (QPushButton),并在按下“X”按钮时删除这些按钮 (deleteLater())。

My problem is that when deleting some of these buttons by pressing the associated X-button, this leaves a small empty space where the buttons were initially, and I therefore wonder how to remove these spaces?我的问题是,当通过按下相关的 X 按钮删除其中一些按钮时,这会在按钮最初所在的位置留下一个小的空白空间,因此我想知道如何删除这些空间?

Image of the empty spaces空白区域的图像

from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLineEdit, QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QGroupBox, QScrollArea, QLabel
from PyQt5.QtCore import Qt
import sys


class MyWindow(QMainWindow):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.setWindowTitle("My Program")
        self.setGeometry(100, 100, 1500, 1500)
        self.initUI()

    def initUI(self):
        widgets = MainWidgets()
        self.setCentralWidget(widgets)


class MainWidgets(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.grid = QGridLayout()
        self.grid.setColumnStretch(0, 1)
        self.grid.setColumnStretch(1, 1)
        self.grid.setColumnStretch(2, 1)
        self.grid.setColumnStretch(3, 1)
        self.grid.setColumnStretch(4, 1)

        self.groupBox = QGroupBox("Labels")
        self.groupBox.setStyleSheet('''
            QGroupBox::title {
                subcontrol-position: top center;
            }
        ''')

        right_column_layout = QVBoxLayout(self.groupBox)
        scrollArea = QScrollArea()
        scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scrollArea.setWidgetResizable(True)
        right_column_layout.addWidget(scrollArea)
        scrollArea.setWidget(RightColWidgets())

        self.grid.addWidget(self.groupBox, 0, 5, 1, 5)
        self.setLayout(self.grid)


class RightColWidgets(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.layout = QVBoxLayout(self)

        self.labelEntry = QLineEdit(self)

        self.addLabelButton = QPushButton(self)
        self.addLabelButton.setText("Add Label")
        self.addLabelButton.clicked.connect(self.addNewLabel)

        self.emptyspace = QLabel(self)

        self.layout.addWidget(self.labelEntry, stretch=0)
        self.layout.addWidget(self.addLabelButton, stretch=0)
        self.layout.addWidget(self.emptyspace, stretch=1)

    def addNewLabel(self):
        labelname = self.labelEntry.text()
        newLabelItems = Labels(self, labelname)

        self.layout.insertWidget(2, newLabelItems)


class Labels(QWidget):
    def __init__(self, parent, labelname, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.mylabelname = labelname
        self.initUI()

    def initUI(self):
        self.labelButton = QPushButton(self)
        self.labelButton.setText(str(self.mylabelname))
        self.labelButton.setStyleSheet("""
            QPushButton {border: 1px solid back; background: rgba(103, 186, 181, 0.5); padding-top: 10px; padding-bottom: 10px}
        """)
        self.labelButton.clicked.connect(self.printbutton)
        self.buttonErase = QPushButton(self)
        self.buttonErase.setText("X")
        self.buttonErase.setStyleSheet("""
            QPushButton {border: 1px solid back; padding-right: 5 px; padding-left: 5 px; padding-top: 10px; padding-bottom: 10px}
        """)
        self.buttonErase.clicked.connect(self.erasebutton)

        layout = QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.labelButton, stretch=1)
        layout.addWidget(self.buttonErase, stretch=0)

    def printbutton(self):
        print('clicked:', self.labelButton.text())

    def erasebutton(self):
        self.labelButton.deleteLater()
        self.buttonErase.deleteLater()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    # app.setStyle('Fusion')
    window = MyWindow()
    window.showMaximized()
    sys.exit(app.exec_())

Deleting the children does not delete the container, so what you see is the empty Labels widget with the spacing of its layout contentsMargins() .删除子项并不会删除容器,因此您看到的是空的Labels小部件,其布局的间距为contentsMargins()

A simple solution could be to directly connect the button with its own deleteLeter() , which automatically deletes its children:一个简单的解决方案是直接将按钮与它自己的deleteLeter()连接起来,它会自动删除它的子元素:

        self.buttonErase.clicked.connect(self.deleteLater)

A better solution would be to connect the signal to the parent and let it do everything necessary in a cleaner way, as you might need to keep track of the existing widgets (for instance, to remove them from the list of currently existing labels):更好的解决方案是将信号连接到级并让它以更简洁的方式完成所有必要的事情,因为您可能需要跟踪现有的小部件(例如,将它们从当前存在的标签列表中删除):

class RightColWidgets(QWidget):
    # ...

    def addNewLabel(self):
        labelname = self.labelEntry.text()
        newLabelItems = Labels(self, labelname)

        self.layout.insertWidget(2, newLabelItems)
        newLabelItems.buttonErase.clicked.connect(
            lambda: self.deleteLabel(newLabelItems))

    def deleteLabel(self, widget):
        self.layout.removeWidget(widget)
        widget.deleteLater()

Obviously, in this case you don't need to connect the clicked signal in the initUi of the Label class anymore.显然,在这种情况下,您不再需要在initUiLabel中连接clicked信号。

Note that layout() is an existing (and dynamic ) property of any QWidget, so you should not overwrite it.请注意, layout()是任何 QWidget 的现有(和动态)属性,因此您不应覆盖它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM