在PyQt5中删除小部件时如何去除黑色space
How to remove black space when deleting widgets in PyQt5
我有一个使用 PyQt5 生成 GUI 的代码,使用户能够基于条目 (QLineEdit) 创建多个按钮 (QPushButton),并在按下“X”按钮时删除这些按钮 (deleteLater() ).
我的问题是,当通过按下关联的 X 按钮删除其中一些按钮时,这会在按钮最初所在的位置留下一个小空 space,因此我想知道如何删除这些 spaces?
空的图像 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_())
删除子项不会删除容器,因此您看到的是空的 Labels
小部件,其布局间距为 contentsMargins()
。
一个简单的解决方案可能是直接将按钮与它自己的 deleteLeter()
连接起来,这会自动删除它的子项:
self.buttonErase.clicked.connect(self.deleteLater)
一个更好的解决方案是将信号连接到父并让它在中做所有必要的事情cleaner 方式,因为您可能需要跟踪现有的小部件(例如,将它们从当前存在的标签列表中删除):
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()
显然,在这种情况下,您不再需要在 Label
class 的 initUi
中连接 clicked
信号。
请注意,layout()
是任何 QWidget 的现有(和 动态)属性,因此您不应覆盖它。
我有一个使用 PyQt5 生成 GUI 的代码,使用户能够基于条目 (QLineEdit) 创建多个按钮 (QPushButton),并在按下“X”按钮时删除这些按钮 (deleteLater() ).
我的问题是,当通过按下关联的 X 按钮删除其中一些按钮时,这会在按钮最初所在的位置留下一个小空 space,因此我想知道如何删除这些 spaces?
空的图像 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_())
删除子项不会删除容器,因此您看到的是空的 Labels
小部件,其布局间距为 contentsMargins()
。
一个简单的解决方案可能是直接将按钮与它自己的 deleteLeter()
连接起来,这会自动删除它的子项:
self.buttonErase.clicked.connect(self.deleteLater)
一个更好的解决方案是将信号连接到父并让它在中做所有必要的事情cleaner 方式,因为您可能需要跟踪现有的小部件(例如,将它们从当前存在的标签列表中删除):
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()
显然,在这种情况下,您不再需要在 Label
class 的 initUi
中连接 clicked
信号。
请注意,layout()
是任何 QWidget 的现有(和 动态)属性,因此您不应覆盖它。