I used Qt Designer to design a GUI and use the command in PyQt5 to convert the .ui file to .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?
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.
For another QMessageBox.about()
requires as first parameter an object of some kind that inherits from QWidget
or also 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:
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. 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.
PyQt I recommend to create another class that uses the class that generates QtDesigner, I assume that the generated file is called 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:
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.
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.
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()
hope this helps.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.