0

我正在尝试在 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,不再删除。附加点的问题相同。

4

0 回答 0