【问题标题】:PyQt5 self referencePyQt5 自我参考
【发布时间】:2018-04-04 12:49:09
【问题描述】:

我使用 Qt Designer 设计了一个 GUI,并使用 PyQt5 中的命令将 .ui 文件转换为 .py。由此,我想在单击按钮时输出一个消息框。我已经在按钮监听器的功能上使用这行代码成功地完成了它:

QtWidgets.QMessageBox.about(MainWindow, "Result", "Invalid number entered!")

我在互联网上搜索过,但我不明白为什么这个不起作用。

QtWidgets.QMessageBox.about(self, "Result", "Invalid number entered!")

self 是否也指 MainWindow?

这里是完整的源代码。

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.setWindowModality(QtCore.Qt.WindowModal)
        #MainWindow.resize(310, 185)
        MainWindow.setFixedSize(310, 185)
        MainWindow.setStyleSheet("#MainWindow\n"
    "{\n"
    "    background-color:qradialgradient(spread:pad, cx:0.5, cy:0.5, 
    radius:1.696, fx:0.5, fy:0.505682, stop:0 rgba(0, 85, 255, 255), stop:1 
    rgba(255, 255, 255, 255))\n"
    "}\n"
    "\n"
    "#firstNo_lineedit, #secondNo_lineedit\n"
    "{\n"
    "    \n"
    "    background-color: rgb(28, 255, 123);\n"
    "}\n"
    "\n"
    "")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.firstNo_lineedit = QtWidgets.QLineEdit(self.centralwidget)
        self.firstNo_lineedit.setGeometry(QtCore.QRect(130, 40, 113, 20))
        self.firstNo_lineedit.setObjectName("firstNo_lineedit")
        self.secondNo_lineedit = QtWidgets.QLineEdit(self.centralwidget)
        self.secondNo_lineedit.setGeometry(QtCore.QRect(130, 70, 113, 20))
        self.secondNo_lineedit.setObjectName("secondNo_lineedit")
        self.calculate_button = QtWidgets.QPushButton(self.centralwidget)
        self.calculate_button.setGeometry(QtCore.QRect(170, 100, 75, 23))
        self.calculate_button.setObjectName("calculate_button")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(60, 40, 81, 20))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(60, 70, 61, 20))
        self.label_2.setObjectName("label_2")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 310, 21))
        self.menubar.setObjectName("menubar")
        self.menuAbout = QtWidgets.QMenu(self.menubar)
        self.menuAbout.setObjectName("menuAbout")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.menubar.addAction(self.menuAbout.menuAction())

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

        # ================= Listeners ===================
        self.calculate_button.clicked.connect(self.basicArithmetic)
        # ============================================

    # ================= Events ===================
    def basicArithmetic(self):
        try:
            firstNo=float(self.firstNo_lineedit.text())
            secondNo=float(self.secondNo_lineedit.text())

            resSum=firstNo+secondNo
            resDiff=firstNo-secondNo
            resMul=firstNo*secondNo
            resDiv=round(firstNo/secondNo,2)

            print("Sum: {}".format(resSum))
            print("Difference: {}".format(resDiff))
            print("Product: {}".format(resMul))
            print("Quotient: {}".format(resDiv))

            toDisplay="Sum: {}".format(resSum)
            toDisplay+="\n"
            toDisplay+="Difference: {}".format(resDiff)
            toDisplay+="\n"
            toDisplay+="Product: {}".format(resMul)
            toDisplay+="\n"
            toDisplay+="Quotient: {}".format(resDiv)

            #QtWidgets.QMessageBox.about(self, "Result", toDisplay)
            QtWidgets.QMessageBox.about(MainWindow, "Result", toDisplay)

        except ValueError:
            #QtWidgets.QMessageBox.about(self, "Result", toDisplay)
            QtWidgets.QMessageBox.about(MainWindow, "Result", "Invalid number entered!")
    # ============================================

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.calculate_button.setText(_translate("MainWindow", "Calculate"))
        self.label.setText(_translate("MainWindow", "First No.:"))
        self.label_2.setText(_translate("MainWindow", "Second No.:"))
        self.menuAbout.setTitle(_translate("MainWindow", "About"))
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python python-3.x pyqt5 qt-designer


    【解决方案1】:

    self 是引用相同实例的类的方法的第一个参数(名称是约定俗成的,不是强制性的)。

    对于另一个QMessageBox.about() 需要一个从QWidget 或None 继承的某种对象作为第一个参数。

    如果我们查看 Qt Designer 生成的类,我们清楚地看到它不是一个小部件,实际上该类的唯一目的是作为一个接口来填充另一个小部件:

    MainWindow = QtWidgets.QMainWindow() # create widget
    ui = Ui_MainWindow() # create interface
    ui.setupUi(MainWindow) # fill widget
    

    因此,您要传递的selfUi_MainWindow 的实例是不合适的,因为它不引用小部件,但MainWindow 是一个小部件,因此它可以在该更改下正常工作。 同样在生成的文件中,您会看到以下消息:

    # WARNING! All changes made in this file will be lost!
    

    该消息是因为如果您想更改设计,您将不得不覆盖您编写的逻辑,例如您的 basicArithmetic 方法,这会使项目无法维持。

    PyQt 我建议创建另一个使用生成 QtDesigner 的类的类,我假设生成的文件名为 design.py

    design.py:

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'design.ui'
    #
    # Created by: PyQt5 UI code generator 5.10.1
    #
    # WARNING! All changes made in this file will be lost!
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.setWindowModality(QtCore.Qt.WindowModal)
            #MainWindow.resize(310, 185)
            MainWindow.setFixedSize(310, 185)
            MainWindow.setStyleSheet("#MainWindow\n"
        "{\n"
        "    background-color:qradialgradient(spread:pad, cx:0.5, cy:0.5," 
        "radius:1.696, fx:0.5, fy:0.505682, stop:0 rgba(0, 85, 255, 255), stop:1" 
        "rgba(255, 255, 255, 255))\n"
        "}\n"
        "\n"
        "#firstNo_lineedit, #secondNo_lineedit\n"
        "{\n"
        "    \n"
        "    background-color: rgb(28, 255, 123);\n"
        "}\n"
        "\n"
        "")
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.firstNo_lineedit = QtWidgets.QLineEdit(self.centralwidget)
            self.firstNo_lineedit.setGeometry(QtCore.QRect(130, 40, 113, 20))
            self.firstNo_lineedit.setObjectName("firstNo_lineedit")
            self.secondNo_lineedit = QtWidgets.QLineEdit(self.centralwidget)
            self.secondNo_lineedit.setGeometry(QtCore.QRect(130, 70, 113, 20))
            self.secondNo_lineedit.setObjectName("secondNo_lineedit")
            self.calculate_button = QtWidgets.QPushButton(self.centralwidget)
            self.calculate_button.setGeometry(QtCore.QRect(170, 100, 75, 23))
            self.calculate_button.setObjectName("calculate_button")
            self.label = QtWidgets.QLabel(self.centralwidget)
            self.label.setGeometry(QtCore.QRect(60, 40, 81, 20))
            self.label.setObjectName("label")
            self.label_2 = QtWidgets.QLabel(self.centralwidget)
            self.label_2.setGeometry(QtCore.QRect(60, 70, 61, 20))
            self.label_2.setObjectName("label_2")
            MainWindow.setCentralWidget(self.centralwidget)
            self.menubar = QtWidgets.QMenuBar(MainWindow)
            self.menubar.setGeometry(QtCore.QRect(0, 0, 310, 21))
            self.menubar.setObjectName("menubar")
            self.menuAbout = QtWidgets.QMenu(self.menubar)
            self.menuAbout.setObjectName("menuAbout")
            MainWindow.setMenuBar(self.menubar)
            self.statusbar = QtWidgets.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
            self.menubar.addAction(self.menuAbout.menuAction())
    
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
            self.calculate_button.setText(_translate("MainWindow", "Calculate"))
            self.label.setText(_translate("MainWindow", "First No.:"))
            self.label_2.setText(_translate("MainWindow", "Second No.:"))
            self.menuAbout.setTitle(_translate("MainWindow", "About"))
    
    if __name__ == "__main__":
        import sys
        app = QtWidgets.QApplication(sys.argv)
        MainWindow = QtWidgets.QMainWindow()
        ui = Ui_MainWindow()
        ui.setupUi(MainWindow)
        MainWindow.show()
        sys.exit(app.exec_())
    

    这个新类可以有以下形式:

    ma​​in.py:

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    from design import Ui_MainWindow
    
    class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
        def __init__(self, *args, **kwargs):
            QtWidgets.QMainWindow.__init__(self, *args, **kwargs)
            self.setupUi(self)  
    
            # ================= Listeners ===================
            self.calculate_button.clicked.connect(self.basicArithmetic)
            # ============================================
    
        # ================= Events ===================
        def basicArithmetic(self):
            try:
                firstNo=float(self.firstNo_lineedit.text())
                secondNo=float(self.secondNo_lineedit.text())
    
                resSum=firstNo+secondNo
                resDiff=firstNo-secondNo
                resMul=firstNo*secondNo
                resDiv=round(firstNo/secondNo,2)
    
                print("Sum: {}".format(resSum))
                print("Difference: {}".format(resDiff))
                print("Product: {}".format(resMul))
                print("Quotient: {}".format(resDiv))
    
                toDisplay="Sum: {}".format(resSum)
                toDisplay+="\n"
                toDisplay+="Difference: {}".format(resDiff)
                toDisplay+="\n"
                toDisplay+="Product: {}".format(resMul)
                toDisplay+="\n"
                toDisplay+="Quotient: {}".format(resDiv)
    
                #QtWidgets.QMessageBox.about(self, "Result", toDisplay)
                QtWidgets.QMessageBox.about(self, "Result", toDisplay)
    
            except ValueError:
                #QtWidgets.QMessageBox.about(self, "Result", toDisplay)
                QtWidgets.QMessageBox.about(self, "Result", "Invalid number entered!")
    
    if __name__ == "__main__":
        import sys
        app = QtWidgets.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())
    

    这就是为什么在许多情况下,self 被视为第一个参数。

    您可以在以下链接中找到更多信息:

    【讨论】:

    • 谢谢!我仍然需要在 OOP 中打下基础。最后一个问题,当Python中的一个类中涉及一个参数时,这意味着什么。例如,像这样:class MainWindow(QMainWindow):
    • @LinkedRom 这就是所谓的继承,就像你继承你父母的特性一样,MainWindow类继承自QMainWindow,所以它有它所有的方法和属性,可以让你创建一个自定义窗口,就像你是你父母的定制版。 :D。这是 OOP 的最佳属性之一,它使我们免于编写成千上万行代码。
    【解决方案2】:

    没有自我指的是Ui_MainWindowclass,其中MainWindow指的是QtWidgets.QMainWindow() 因此,当您说QtWidgets.QMessageBox.about(self, "Result", toDisplay) 时,它会将Ui_MainWindow 视为父母QWidget,这是不正确的。

    这次当您调用QtWidgets.QMessageBox.about(MainWindow, "Result", toDisplay) 时,您的代码将运行良好,因为MainWindow 是有效的QWidget,即QtWidgets.QMainWindow()

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-02-13
      • 1970-01-01
      • 2014-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-13
      • 1970-01-01
      相关资源
      最近更新 更多