且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

QDialog 中 QLineEdit 小部件的奇怪行为,绑定按钮功能

更新时间:2023-11-14 16:32:46

根据

I am new with programming in pyqt, so maybe i am wrong with this, but i have found that self.lineEdit on Enter pressed calls for button's function, even when self.handleKeyRelease is commented. This is minimum of code and first place where i have found that strange behavior.

self.lineEdit = QtGui.QLineEdit(self.frame)

# self.lineEdit.keyReleaseEvent = self.handleKeyRelease

self.pushButton = QtGui.QPushButton(self.frame)
self.pushButton.clicked.connect(lambda event: self._insertIntoCategories(db, self.lineEdit))

second place of this same behaviour are ,dynamically made, form-like widgets (there is one LineEdit and 3 buttons in a row)

        self.lineEdit_2 = QtGui.QLineEdit(self.frame_3)
        self.lineEdit_2.setText(item[1])    


        # ------------------------------------  block ------------------------------------------------- #

        self.pushButton_4 = QtGui.QPushButton(self.frame_3)       

        self.pushButton_4.clicked.connect(lambda event, id=item[0], le=self.lineEdit_2: self.modal('edit', 'Are you sure you want to rename this category ?', id, le))

        # ------------------------------------  block ------------------------------------------------- #

        self.pushButton_3 = QtGui.QPushButton(self.frame_3)

        self.pushButton_3.clicked.connect(lambda event, id=item[0]: self.__chIcon(id))


        # ------------------------------------  block ------------------------------------------------- #

        self.pushButton_2 = QtGui.QPushButton(self.frame_3)

        self.pushButton_2.clicked.connect(lambda event, id=item[0], le=self.lineEdit_2: self.modal('delete', 'Are you sure you want to delete this category ?', id, le))

each of this buttons works fine, but each entry on Enter press(or release) again calls for function from previous part of the code (self.pushButton's function) self._insertIntoCategories If this code is not sufficient, there is full code on github if needed.

fully executable code :

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_Form(object):

    def setupUi(self):
        self.Form = QtGui.QDialog()
        Form = self.Form
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(504, 550)
        self.verticalLayout = QtGui.QVBoxLayout(Form)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))

        self.frame = QtGui.QFrame(Form)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
        self.frame.setSizePolicy(sizePolicy)
        self.frame.setMinimumSize(QtCore.QSize(0, 50))
        self.frame.setStyleSheet(_fromUtf8("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0  green, stop:1 white);"))
        self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtGui.QFrame.Raised)
        self.frame.setObjectName(_fromUtf8("frame"))

        self.horizontalLayout_2 = QtGui.QHBoxLayout(self.frame)
        self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))

        self.horizontalLayout = QtGui.QHBoxLayout()
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))

        # -------------- start of widget definitions -------------------------- #

        # THIS IS FIRTS INPUT #

        self.lineEdit = QtGui.QLineEdit(self.frame)
        self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
        self.horizontalLayout.addWidget(self.lineEdit)

        # AND THIS IS FIRST BUTTON

        self.pushButton = QtGui.QPushButton(self.frame)
        self.pushButton.setMinimumSize(QtCore.QSize(50, 0))
        self.pushButton.setStyleSheet(_fromUtf8("border-image: url(imgs/required/btns/add.png);background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 white, stop:1 white);"))
        self.pushButton.setText(_fromUtf8(""))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))
        self.pushButton.clicked.connect(lambda event: self.btnBehavior())
        self.horizontalLayout.addWidget(self.pushButton)

        # -------------- end of widget definitions -------------------------- #


        self.horizontalLayout_2.addLayout(self.horizontalLayout)

        self.verticalLayout.addWidget(self.frame)

        self.frame_2 = QtGui.QFrame(Form)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth())
        self.frame_2.setSizePolicy(sizePolicy)
        self.frame_2.setStyleSheet(_fromUtf8("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 green, stop:1 white);"))
        self.frame_2.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_2.setObjectName(_fromUtf8("frame_2"))

        self.verticalLayout_2 = QtGui.QVBoxLayout(self.frame_2)
        self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))

        self.verticalLayout_3 = QtGui.QVBoxLayout()
        self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))

        self.frame_3 = QtGui.QFrame(self.frame_2)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.frame_3.sizePolicy().hasHeightForWidth())
        self.frame_3.setSizePolicy(sizePolicy)
        self.frame_3.setStyleSheet(_fromUtf8("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 white, stop:1 green);"))
        self.frame_3.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_3.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_3.setObjectName(_fromUtf8("frame_3"))

        self.horizontalLayout_3 = QtGui.QHBoxLayout(self.frame_3)
        self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))


        # -------------- start of widget definitions, second row -------------------------- #

        # THIS IS SECOND INPUT

        self.lineEdit_2 = QtGui.QLineEdit(self.frame_3)

        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.lineEdit_2.sizePolicy().hasHeightForWidth())
        self.lineEdit_2.setSizePolicy(sizePolicy)
        self.lineEdit_2.setObjectName(_fromUtf8("lineEdit_2"))

        self.horizontalLayout_3.addWidget(self.lineEdit_2)


        #THIS IS SECOND, THIRD AND FOURTH BUTTONS

        self.pushButton_4 = QtGui.QPushButton(self.frame_3)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton_4.sizePolicy().hasHeightForWidth())
        self.pushButton_4.setSizePolicy(sizePolicy)
        self.pushButton_4.setStyleSheet(_fromUtf8("border-image: url(imgs/required/btns/edit.jpg);background-color: transparent;"))
        self.pushButton_4.setText(_fromUtf8(""))
        self.pushButton_4.clicked.connect(lambda event: self.btnBehavior())
        self.pushButton_4.setObjectName(_fromUtf8("pushButton_4"))

        self.horizontalLayout_3.addWidget(self.pushButton_4)
        self.pushButton_3 = QtGui.QPushButton(self.frame_3)
        self.pushButton_3.setStyleSheet(_fromUtf8("border-image: url(imgs/required/btns/ch_pic.png); background-color: transparent;"))
        self.pushButton_3.setText(_fromUtf8(""))
        self.pushButton_3.setObjectName(_fromUtf8("pushButton_3"))
        self.pushButton_3.clicked.connect(lambda event: self.btnBehavior())
        self.horizontalLayout_3.addWidget(self.pushButton_3)

        self.pushButton_2 = QtGui.QPushButton(self.frame_3)
        self.pushButton_2.setStyleSheet(_fromUtf8("border-image: url(imgs/required/btns/trash.png);background-color: transparent;"))
        self.pushButton_2.setText(_fromUtf8(""))
        self.pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
        self.pushButton_2.clicked.connect(lambda event: self.btnBehavior())
        self.horizontalLayout_3.addWidget(self.pushButton_2)

        # -------------- end of widget definitions -------------------------- #

        self.verticalLayout_3.addWidget(self.frame_3)
        self.verticalLayout_2.addLayout(self.verticalLayout_3)

        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)

        self.verticalLayout_2.addItem(spacerItem)
        self.verticalLayout.addWidget(self.frame_2)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)


    def retranslateUi(self, Form):
        Form.setWindowTitle(_translate("Form", "Form", None))
        self.pushButton_4.setToolTip(_translate("Form", "<html><head/><body><p>rename</p></body></html>", None))
        self.pushButton_3.setToolTip(_translate("Form", "<html><head/><body><p>picture</p></body></html>", None))
        self.pushButton_2.setToolTip(_translate("Form", "<html><head/><body><p>delete</p></body></html>", None))
        self.pushButton_2.setWhatsThis(_translate("Form", "<html><head/><body><p>delete</p></body></html>", None))

    def btnBehavior(self):
        print('btn clicked');


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    # Form = QtGui.QDialog()
    ui = Ui_Form()
    ui.setupUi()
    ui.Form.show()
    sys.exit(app.exec_())

According to the documentation:

autoDefault : bool

This property holds whether the push button is an auto default button

If this property is set to true then the push button is an auto default button.

In some GUI styles a default button is drawn with an extra frame around it, up to 3 pixels or more. Qt automatically keeps this space free around auto-default buttons, i.e., auto-default buttons may have a slightly larger size hint.

This property's default is true for buttons that have a QDialog parent; otherwise it defaults to false.

See the default property for details of how default and auto-default interact.

That is, this is the responsible property of this problem. The workaround is to set the autoDefault property to False for all QPushButtons.

To do it in a simple way I have restructured your code, to do this put the state of Qt Designer has generated and then implemented the logic that implements that design, given this is my proposed solution:

class Dialog(QtGui.QDialog, Ui_Form):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
        self.setupUi(self)

        for pb in self.findChildren(QtGui.QPushButton):
            pb.setAutoDefault(False)

        self.pushButton.clicked.connect(self.btnBehavior)

    def btnBehavior(self):
        print('btn clicked')

As @ekhumoro says you can do the same with Qt Designer, .