简体   繁体   English

PyQt5自我参考

[英]PyQt5 self reference

I used Qt Designer to design a GUI and use the command in PyQt5 to convert the .ui file to .py. 我使用Qt Designer来设计GUI,并使用PyQt5中的命令将.ui文件转换为.py。 From that, I want to output a messagebox when a button is clicked. 由此,我想在单击按钮时输出一个消息框。 I have successfully done it using this line of code on the function of the button listener: 我已经在按钮侦听器的功能上使用此行代码成功完成了此操作:

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

I have searched around the internet but I don't understand why this one don't work. 我已经在互联网上进行搜索,但是我不明白为什么这一项不起作用。

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

Does the self their refer to the MainWindow also? 他们自己也引用MainWindow吗?

Here is the full source code. 这是完整的源代码。

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_())

self is the first parameter of the methods (the name is by convention, is not mandatory) of a class that refers to the instance of the same. self是引用相同实例的类的方法的第一个参数(名称是按惯例,不是必需的)。

For another QMessageBox.about() requires as first parameter an object of some kind that inherits from QWidget or also None. 对于另一个QMessageBox.about()需要一个继承自QWidget或None的某种对象作为第一个参数。

If we review the class generated by Qt Designer, we clearly see that it is not a widget, in fact the only objective of that class is to be an interface to fill in another widget: 如果我们查看由Qt Designer生成的类,我们会清楚地看到它不是小部件,实际上,该类的唯一目的是成为填充其他小部件的接口:

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

Therefore the self , the instance of Ui_MainWindow , you want to pass is not appropriate because it does not refer to the widget, but the MainWindow is a widget, so it works correctly with that change. 因此,要传递的self ,即Ui_MainWindow的实例是Ui_MainWindow ,因为它不引用窗口小部件,但是MainWindow是窗口小部件,因此它可以正确地使用此更改。 Also within the generated file you have the following message: 此外,在生成的文件中,您还会显示以下消息:

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

That message is because if you want to change the design you will have to overwrite the logic that you wrote, such as your basicArithmetic method, which makes the project untenable. 该消息是因为,如果您要更改设计,则必须覆盖您编写的逻辑,例如basicArithmetic方法,这会使项目无法使用。

PyQt I recommend to create another class that uses the class that generates QtDesigner, I assume that the generated file is called design.py PyQt我建议创建另一个使用生成QtDesigner的类的类,我假设生成的文件名为design.py

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_())

This new class can have the following form: 该新类可以具有以下形式:

main.py: main.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_())

And that is the reason why, in many cases, self is seen as the first parameter. 这就是为什么在很多情况下, self被视为第一个参数的原因。

You can find more information at the following link: 您可以在以下链接中找到更多信息:

No self refers to Ui_MainWindow class where MainWindow reffers to QtWidgets.QMainWindow() So when you say QtWidgets.QMessageBox.about(self, "Result", toDisplay) it will treat Ui_MainWindow as a parent QWidget which is not correct. 没有自引用指向MainWindow继承于QtWidgets.QMainWindow() Ui_MainWindow类,因此,当您说QtWidgets.QMessageBox.about(self, "Result", toDisplay) ,会将Ui_MainWindow视为不正确的父QWidget

when you call QtWidgets.QMessageBox.about(MainWindow, "Result", toDisplay) this time your code will run fine because MainWindow is a valid QWidget ie QtWidgets.QMainWindow() 这次调用QtWidgets.QMessageBox.about(MainWindow, "Result", toDisplay)时,您的代码将运行良好,因为MainWindow是有效的QWidgetQtWidgets.QMainWindow()

hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM