我正在尝试在 lineedit 内动态创建插入删除工具按钮,并将插槽与删除工具相关联。使问题复杂化的是插槽具有参数,即要删除的行的行编辑和标签。因此,我必须使用lambda
. 问题是删除按钮仅删除一行并且顺序不正确。我已经尝试过functools.partial
使用 lambda,i=i
但两者都不起作用。以下是我拥有的代码。
from functools import partial
def __init__(self, iface, parent=None):
remove_icon = ':/plugins/stdm/images/icons/remove.png'
for i, (line_widget, label) in enumerate(
zip(self.coordFormContainer.findChildren(QLineEdit),
self.coordFormContainer.findChildren(QLabel)
)
):
self.remove_button = QToolButton(line_widget)
self.remove_button.setCursor(Qt.PointingHandCursor)
self.remove_button.setFocusPolicy(Qt.NoFocus)
self.remove_button.setIcon(QIcon(remove_icon))
self.remove_button.setStyleSheet(
'background: transparent; '
'border: none;'
)
self.remove_button.setToolTip(
QApplication.translate(
'Window',
'Remove this point'
)
)
self.remove_button.setStyleSheet(
'QToolTip { '
'color: #222; '
'background-color: #ddd; '
'border: 1px solid #eee; '
'}'
)
layout = QHBoxLayout(line_widget)
layout.addWidget(self.remove_button, 0, Qt.AlignRight)
layout.setSpacing(0)
layout.setMargin(0)
self.remove_button.setObjectName(
'remove_button_'+str(i)
)
# Signal for removing rows using remove_button
self.remove_button.clicked.connect(
partial(lambda: self.remove_self_row(line_widget, label))
)
def remove_self_row(self, line_widget, label):
line_widget.setParent(None)
label.setParent(None)
编辑:这个问题的独特之处在于,参数也是动态的,因为它们来自循环。
编辑:我在下面添加了完整的可运行代码。
from functools import partial
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Points(object):
def setupUi(self, Points):
Points.setObjectName(_fromUtf8("Points"))
Points.resize(458, 418)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Points.sizePolicy().hasHeightForWidth())
Points.setSizePolicy(sizePolicy)
self.verticalLayout_3 = QtGui.QVBoxLayout(Points)
self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
self.coordFormContainer = QtGui.QWidget(Points)
self.coordFormContainer.setObjectName(_fromUtf8("coordFormContainer"))
self.verticalLayout_5 = QtGui.QVBoxLayout(self.coordFormContainer)
self.verticalLayout_5.setObjectName(_fromUtf8("verticalLayout_5"))
self.scrollArea = QtGui.QScrollArea(self.coordFormContainer)
self.scrollArea.setFrameShape(QtGui.QFrame.NoFrame)
self.scrollArea.setLineWidth(0)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName(_fromUtf8("scrollArea"))
self.scrollAreaWidgetContents = QtGui.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 414, 374))
self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents"))
self.verticalLayout_2 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents)
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
self.horizontalLayout_7 = QtGui.QHBoxLayout()
self.horizontalLayout_7.setObjectName(_fromUtf8("horizontalLayout_7"))
self.AddPointButton = QtGui.QPushButton(self.scrollAreaWidgetContents)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.AddPointButton.sizePolicy().hasHeightForWidth())
self.AddPointButton.setSizePolicy(sizePolicy)
self.AddPointButton.setObjectName(_fromUtf8("AddPointButton"))
self.horizontalLayout_7.addWidget(self.AddPointButton)
self.RemovePoint = QtGui.QPushButton(self.scrollAreaWidgetContents)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.RemovePoint.sizePolicy().hasHeightForWidth())
self.RemovePoint.setSizePolicy(sizePolicy)
self.RemovePoint.setObjectName(_fromUtf8("RemovePoint"))
self.horizontalLayout_7.addWidget(self.RemovePoint)
self.verticalLayout_2.addLayout(self.horizontalLayout_7)
self.formLayout_2 = QtGui.QFormLayout()
self.formLayout_2.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
self.formLayout_2.setObjectName(_fromUtf8("formLayout_2"))
self.p1Label = QtGui.QLabel(self.scrollAreaWidgetContents)
self.p1Label.setObjectName(_fromUtf8("p1Label"))
self.formLayout_2.setWidget(1, QtGui.QFormLayout.LabelRole, self.p1Label)
self.p1LineEdit = QtGui.QLineEdit(self.scrollAreaWidgetContents)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.p1LineEdit.sizePolicy().hasHeightForWidth())
self.p1LineEdit.setSizePolicy(sizePolicy)
self.p1LineEdit.setInputMethodHints(QtCore.Qt.ImhNone)
self.p1LineEdit.setObjectName(_fromUtf8("p1LineEdit"))
self.formLayout_2.setWidget(1, QtGui.QFormLayout.FieldRole, self.p1LineEdit)
self.p2Label = QtGui.QLabel(self.scrollAreaWidgetContents)
self.p2Label.setObjectName(_fromUtf8("p2Label"))
self.formLayout_2.setWidget(2, QtGui.QFormLayout.LabelRole, self.p2Label)
self.p2LineEdit = QtGui.QLineEdit(self.scrollAreaWidgetContents)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.p2LineEdit.sizePolicy().hasHeightForWidth())
self.p2LineEdit.setSizePolicy(sizePolicy)
self.p2LineEdit.setObjectName(_fromUtf8("p2LineEdit"))
self.formLayout_2.setWidget(2, QtGui.QFormLayout.FieldRole, self.p2LineEdit)
self.p3Label = QtGui.QLabel(self.scrollAreaWidgetContents)
self.p3Label.setObjectName(_fromUtf8("p3Label"))
self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.p3Label)
self.p3LineEdit = QtGui.QLineEdit(self.scrollAreaWidgetContents)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.p3LineEdit.sizePolicy().hasHeightForWidth())
self.p3LineEdit.setSizePolicy(sizePolicy)
self.p3LineEdit.setObjectName(_fromUtf8("p3LineEdit"))
self.formLayout_2.setWidget(3, QtGui.QFormLayout.FieldRole, self.p3LineEdit)
self.p4Label = QtGui.QLabel(self.scrollAreaWidgetContents)
self.p4Label.setObjectName(_fromUtf8("p4Label"))
self.formLayout_2.setWidget(4, QtGui.QFormLayout.LabelRole, self.p4Label)
self.p4LineEdit = QtGui.QLineEdit(self.scrollAreaWidgetContents)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.p4LineEdit.sizePolicy().hasHeightForWidth())
self.p4LineEdit.setSizePolicy(sizePolicy)
self.p4LineEdit.setObjectName(_fromUtf8("p4LineEdit"))
self.formLayout_2.setWidget(4, QtGui.QFormLayout.FieldRole, self.p4LineEdit)
self.verticalLayout_2.addLayout(self.formLayout_2)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.verticalLayout_5.addWidget(self.scrollArea)
self.verticalLayout_3.addWidget(self.coordFormContainer)
self.retranslateUi(Points)
QtCore.QMetaObject.connectSlotsByName(Points)
def retranslateUi(self, Points):
Points.setWindowTitle(_translate("Points", "Window", None))
self.AddPointButton.setToolTip(_translate("Points", "<html><head/><body><p>Test Tool</p></body></html>", None))
self.AddPointButton.setText(_translate("Points", "Add point", None))
self.RemovePoint.setText(_translate("Points", "Remove Point", None))
self.p1Label.setText(_translate("Points", "P1", None))
self.p1LineEdit.setPlaceholderText(_translate("Points", "788524.328102, 341547.783899", None))
self.p2Label.setText(_translate("Points", "P2", None))
self.p3Label.setText(_translate("Points", "P3", None))
self.p4Label.setText(_translate("Points", "P4", None))
class Window(QDialog, Ui_Points):
def __init__(self):
QDialog.__init__(self)
self.setupUi(self)
self.points = 4
self.coordFormContainer.setFixedHeight(300)
self.coordFormContainer.setFixedWidth(400)
self.AddPointButton.clicked.connect(
self.add_row
)
self.RemovePoint.clicked.connect(
self.remove_row
)
for i, (line_widget, label) in enumerate(
zip(self.coordFormContainer.findChildren(QLineEdit),
self.coordFormContainer.findChildren(QLabel)
)
):
self.remove_button = QToolButton(line_widget)
self.remove_button.setText('x')
self.remove_button.setCursor(Qt.PointingHandCursor)
self.remove_button.setFocusPolicy(Qt.NoFocus)
self.remove_button.setStyleSheet(
'background: red; '
'color: red;'
'border: none;'
)
self.remove_button.setToolTip(
QApplication.translate(
'Window',
'Remove this point'
)
)
self.remove_button.setStyleSheet(
'QToolTip { '
'color: #555; '
'background-color: #ddd; '
'border: 1px solid #eee; '
'}'
)
layout = QHBoxLayout(line_widget)
layout.addWidget(self.remove_button, 0, Qt.AlignRight)
layout.setSpacing(0)
layout.setMargin(0)
self.remove_button.setObjectName(
'remove_button_'+str(i)
)
# Signal for removing rows using remove_button
self.remove_button.clicked.connect(
partial(lambda: self.remove_self_row(line_widget, label))
)
def remove_self_row(self, line_widget, label):
"""
A slot raised to remove parent lineedit of a close button.
:param line_widget: The lineedit to be removed
:param label: The lable to be removed
:return:
"""
line_widget.setParent(None)
label.setParent(None)
def add_row (self):
"""
A slot raised to add new point row.
:return: None
"""
self.points = self.points + 1
self.label = QLabel()
self.label.setObjectName(
'p'+str(self.points)+'Label'
)
self.label.setText(
"P"+str(self.points)
)
self.formLayout_2.setWidget(
self.points,
QFormLayout.LabelRole,
self.label
)
self.line_edit = QLineEdit()
self.line_edit.setObjectName(
'p'+str(self.points)+'LineEdit'
)
self.formLayout_2.setWidget(
self.points,
QFormLayout.FieldRole,
self.line_edit
)
# add remove button
self.add_remove_button(self.line_edit)
def add_remove_button(self, line_widget):
"""
Adds the remove button on the lineedit specified
:param line_widget: The parent lineedit of the remove button
:return:
"""
self.remove_button = QToolButton(line_widget)
self.remove_button.setCursor(Qt.PointingHandCursor)
self.remove_button.setFocusPolicy(Qt.NoFocus)
self.remove_button.setText('x')
self.remove_button.setStyleSheet(
'background: red; '
'color: red;'
'border: none;'
)
self.remove_button.setToolTip(
QApplication.translate(
'Point',
'Remove this point'
)
)
self.remove_button.setStyleSheet(
'QToolTip { '
'color: #555; '
'background-color: #ddd; '
'border: 1px solid #eee; '
'}'
)
layout = QHBoxLayout(line_widget)
layout.addWidget(self.remove_button, 0, Qt.AlignRight)
layout.setSpacing(0)
layout.setMargin(0)
def remove_row(self):
"""
A slot raised to remove point row.
:return: None
"""
try:
# Remove label and lineedit
self.formLayout_2.itemAt(
self.points, QFormLayout.FieldRole
).widget().setParent(None)
self.formLayout_2.itemAt(
self.points, QFormLayout.LabelRole
).widget().setParent(None)
self.points = self.points - 1
except AttributeError:
return
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
window.resize(320, 240)
sys.exit(app.exec_())
要重现该问题,请单击其中一个删除按钮。它只删除 P4,不再删除。附加点的问题相同。