簡體   English   中英

刪除 PyQt5 中的小部件時如何刪除黑色空間

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

我有一個代碼可以使用 PyQt5 生成 GUI,它使用戶能夠基於條目 (QLineEdit) 創建多個按鈕 (QPushButton),並在按下“X”按鈕時刪除這些按鈕 (deleteLater())。

我的問題是,當通過按下相關的 X 按鈕刪除其中一些按鈕時,這會在按鈕最初所在的位置留下一個小的空白空間,因此我想知道如何刪除這些空間?

空白區域的圖像

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_())

刪除子項並不會刪除容器,因此您看到的是空的Labels小部件,其布局的間距為contentsMargins()

一個簡單的解決方案是直接將按鈕與它自己的deleteLeter()連接起來,它會自動刪除它的子元素:

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

更好的解決方案是將信號連接到級並讓它以更簡潔的方式完成所有必要的事情,因為您可能需要跟蹤現有的小部件(例如,將它們從當前存在的標簽列表中刪除):

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()

顯然,在這種情況下,您不再需要在initUiLabel中連接clicked信號。

請注意, layout()是任何 QWidget 的現有(和動態)屬性,因此您不應覆蓋它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM