Pyqt - 我的标准 "Apply" 按钮发出什么信号,我如何为它编写插槽?

Pyqt - What signal does my standard "Apply" button emit and how do I write the slot for it?

我正在学习 pyqt,我正在尝试了解标准按钮。我只是在学习,所以如果我做错了什么,请告诉我。

我在 QT Designer 中创建了一个带有一些标准按钮的简单 UI。

我注意到 accepted() 和 rejected() 信号被连接到接受和拒绝槽,所以我写了它们。 “确定”按钮和“取消”按钮按预期工作,但“应用”按钮根本没有反应。如何将应用按钮连接到插槽?

sample.py - 这是我的示例应用程序代码:

import sys
from PyQt4 import QtGui

import designer

class SampleApp(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self,parent)
        self.ui = designer.Ui_Dialog()
        self.ui.setupUi(self)

    def reject(w):
        print("reject", w)
        w.close()

    def accept(w):
        print("accept", w)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    myapp = SampleApp()
    myapp.show()
    sys.exit(app.exec_())

designer.py - 这是自动生成的 QT Designer 代码:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'designer.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!

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_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(554, 399)
        self.buttonBox = QtGui.QDialogButtonBox(Dialog)
        self.buttonBox.setGeometry(QtCore.QRect(190, 340, 341, 32))
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Apply|QtGui.QDialogButtonBox.Close|QtGui.QDialogButtonBox.Ok)
        self.buttonBox.setCenterButtons(False)
        self.buttonBox.setObjectName(_fromUtf8("buttonBox"))

        self.retranslateUi(Dialog)
        QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), Dialog.accept)
        QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))

您需要从 QDialogButtonBox 获取按钮并将 clicked 信号连接到所需的插槽。另外,我建议您使用更直观的 new-style signal and slots 支持:

您可以在下面定义要触发的插槽。您应该使用 @pyqtSlot() 装饰器来装饰它们。它也可以在没有装饰器的情况下工作(更多信息在文档页面)。

import sys
import designer

from PyQt4 import QtGui, QtCore


class SampleApp(QtGui.QWidget):

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self,parent)
        self.ui = designer.Ui_Dialog()
        self.ui.setupUi(self)

    @QtCore.pyqtSlot()
    def reject(self):
        print("reject")
        self.close()

    @QtCore.pyqtSlot()
    def accept(self):
        print("accept")

    @QtCore.pyqtSlot()
    def apply(self):
        print("apply")


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    myapp = SampleApp()
    myapp.show()
    sys.exit(app.exec_())

在下面,您将按钮的 clicked 操作连接到您在此处定义的插槽。请注意,对于 CloseOk 这并不是真正必要的,因为在使用 StandardButtons 时,如果程序员未指定,PyQt 会自动将它们连接到默认操作。尽管我手动连接了它们,所以您可以了解发生了什么。

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'designer.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!

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

    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(554, 399)
        self.buttonBox = QtGui.QDialogButtonBox(Dialog)
        self.buttonBox.setGeometry(QtCore.QRect(190, 340, 341, 32))
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Apply|QtGui.QDialogButtonBox.Close|QtGui.QDialogButtonBox.Ok)
        self.buttonBox.setCenterButtons(False)
        self.buttonBox.setObjectName(_fromUtf8("buttonBox"))

        self.retranslateUi(Dialog)

        self.buttonBox.button(QtGui.QDialogButtonBox.Close).clicked.connect(Dialog.reject)
        self.buttonBox.button(QtGui.QDialogButtonBox.Ok).clicked.connect(Dialog.accept)
        self.buttonBox.button(QtGui.QDialogButtonBox.Apply).clicked.connect(Dialog.apply)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))

您需要在小部件中手动连接来自 Apply 按钮的 clicked 信号。

class SampleApp(QtGui.QWidget):

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self,parent)
        self.ui = designer.Ui_Dialog()
        self.ui.setupUi(self)
        btn = self.ui.buttonBox.button(QtGui.QDialogButtonBox.Apply)
        btn.clicked.connect(self.accept)

您不需要为 accept()reject() 编写插槽,因为 QDialog class 已经有了它们。

当您创建一个新窗体并选择“带按钮的对话框”时,它将添加一个带有确定和取消按钮的按钮框,并且 accepted()/rejected() 信号将自动连接到对话框的现有 accept()reject() 个插槽。

但请注意,按钮和信号之间没有一对一的关系。相反,有一组 button roles, and each standard button 被分配了其中一个角色。所有带有 AcceptRole 的按钮都会发出 accepted() 信号,带有 RejectRole 的按钮会发出 rejected() 信号,而带有 HelpRole 的按钮会发出 helpRequested()信号。但是其他角色(例如 ApplyRole)除了 clicked().

之外不会发出任何特定信号

要处理这些其他按钮,您可以直接连接到每个按钮:

button = self.ui.buttonBox.button(QDialogButtonBox.Apply)
button.clicked.connect(self.handleApply)

或者像这样在一个槽中处理它们:

class SampleApp(QWidget):  
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = designer.Ui_Dialog()
        self.ui.setupUi(self)
        self.ui.buttonBox.clicked.connect(self.handleButtonClick)

    def handleButtonClick(self, button):
        role = self.buttonBox.buttonRole(button)
        if role == QDialogButtonBox.ApplyRole:
            print('Apply Clicked')
        elif role == QDialogButtonBox.ResetRole:
            print('Reset Clicked')        
        # and so on...