25

In normal Python (3.x) we always use showerror() from the tkinter module to display an error message but what should I do in PyQt5 to display exactly the same message type as well?

Ramón Wilhelm
  • 967
  • 2
  • 18
  • 39

7 Answers7

43

Don't forget to call .exec_() to display the error:

from PyQt5.QtWidgets import QMessageBox

msg = QMessageBox()
msg.setIcon(QMessageBox.Critical)
msg.setText("Error")
msg.setInformativeText('More information')
msg.setWindowTitle("Error")
msg.exec_()
djvg
  • 11,722
  • 5
  • 72
  • 103
NShiell
  • 551
  • 4
  • 7
35

Qt includes an error-message specific dialog class QErrorMessage which you should use to ensure your dialog matches system standards. To show the dialog just create a dialog object, then call .showMessage(). For example:

error_dialog = QtWidgets.QErrorMessage()
error_dialog.showMessage('Oh no!')

Here is a minimal working example script:

import PyQt5
from PyQt5 import QtWidgets

app = QtWidgets.QApplication([])

error_dialog = QtWidgets.QErrorMessage()
error_dialog.showMessage('Oh no!')

app.exec_()
mfitzp
  • 15,275
  • 7
  • 50
  • 70
8

Assuming you are in a QWidget from which you want to display an error message, you can simply use QMessageBox.critical(self, "Title", "Message"), replace self by another (main widget for example) if you are not is a QWidget class.


Edit: even if you are not in a QWidget (or don't want to inherit from it), you can just use None as parent with for instance QMessageBox.critical(None, "Title", "Message").


Edit, here is an example of how to use it:

# -*-coding:utf-8 -*

from PyQt5.QtWidgets import QApplication, QMessageBox
import sys

# In this example, success is False by default, and
#  - If you press Cancel, it will ends with False,
#  - If you press Retry until i = 3, it will end with True


expectedVal = 3


def MyFunction(val: int) -> bool:
    return val == expectedVal


app = QApplication(sys.argv)
i = 1
success = MyFunction(i)
while not success:
    # Popup with several buttons, manage below depending on choice
    choice = QMessageBox.critical(None,
                                  "Error",
                                  "i ({}) is not expected val ({})".format(i, expectedVal),
                                  QMessageBox.Retry | QMessageBox.Cancel)
    if choice == QMessageBox.Retry:
        i += 1
        print("Retry with i = {}".format(i))
        success = MyFunction(i)
    else:
        print("Cancel")
        break

if success:
    # Standard popup with only OK button
    QMessageBox.information(None, "Result", "Success is {}".format(success))
else:
    # Standard popup with only OK button
    QMessageBox.critical(None, "Result", "Success is {}".format(success))

gluttony
  • 402
  • 6
  • 14
  • Thanks for this! Could you also tell me how to proceed when the user clicks on the popping up button? – Ben Nov 28 '22 at 13:00
  • 1
    You're welcome, what do you mean by popping up button ? Do you mean how to proceed depending on which button user selects ? – gluttony Nov 28 '22 at 15:16
  • Yes, when I use your above code, a message box with a single button appears. But when I click this one, python runs into an unhandled exception and I guess his is because it is not defined what happens when clicking this button? – Ben Nov 29 '22 at 05:59
  • 1
    Oh, weird, I never had this issue, I edit my answer with a small example on how to manage a popup with different buttons (and also popup with just one button) if it can help, and you can try this example actually works for you, also, from what I've see, a thing that can cause exception is not having created a `QApplication` when using `QMessageBox.critical`. – gluttony Nov 30 '22 at 09:05
6

All above options didn't work for me using Komodo Edit 11.0. Just had returned "1" or if not implemented "-1073741819".

Usefull for me was: Vanloc's solution.

def my_exception_hook(exctype, value, traceback):
    # Print the error and traceback
    print(exctype, value, traceback)
    # Call the normal Exception hook after
    sys._excepthook(exctype, value, traceback)
    sys.exit(1)

# Back up the reference to the exceptionhook
sys._excepthook = sys.excepthook

# Set the exception hook to our wrapping function
sys.excepthook = my_exception_hook
ZF007
  • 3,708
  • 8
  • 29
  • 48
6

To show a message box, you can call this def:

from PyQt5.QtWidgets import QMessageBox, QWidget

MainClass(QWidget):
    def __init__(self):
        super().__init__()

    def clickMethod(self):
        QMessageBox.about(self, "Title", "Message")
Karam Qusai
  • 713
  • 12
  • 16
4

The following should work:

msg = QMessageBox()
msg.setIcon(QMessageBox.Critical)
msg.setText("Error")
msg.setInformativeText(e)
msg.setWindowTitle("Error")

It is not the exact same message type (different GUI's) but fairly close. e is the expression for an Error in python3

Hope that helped, Narusan

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Narusan
  • 482
  • 1
  • 5
  • 18
0
import sys
from PyQt5.QtWidgets import QMessageBox
import PyQt5
from PyQt5 import QtWidgets
"""
Stadard button
QMessageBox.Ok
QMessageBox.Open
QMessageBox.Save
QMessageBox.Cancel
QMessageBox.Close
QMessageBox.Yes
QMessageBox.No
QMessageBox.Abort
QMessageBox.Retry
QMessageBox.Ignore
"""

class MessageBox(QMessageBox):
    def __init__(self, parent=None):
        super().__init__(parent)
        
    #showinfo    
    def showinfo(self,title,text):
        self.setWindowTitle(title)
        self.setText(text)
        
        self.setIcon(QMessageBox.Information)
        self.standard_button=QMessageBox.Ok
        self.setStandardButtons(self.standard_button)
        return self.execute()


    #showwarning
    def showwarning(self,title,text):
        self.setWindowTitle(title)
        self.setText(text)
        self.setIcon(QMessageBox.Warning)
        self.standard_button=QMessageBox.Ok
        self.setStandardButtons(self.standard_button)
        return self.execute()


    #showerror
    def showerror(self,title,text):
        
        self.setWindowTitle(title)
        self.setText(text)
        self.setIcon(QMessageBox.Critical)
        self.standard_button=QMessageBox.Ok
        self.setStandardButtons(self.standard_button)
        return self.execute()
       


    #askyesno
    def askyesno(self,title,text):
        self.setWindowTitle(title)
        self.setText(text)
        self.setIcon(QMessageBox.Question)
        self.standard_button=QMessageBox.Yes | QMessageBox.No
        self.setStandardButtons(self.standard_button)
        return self.execute()


    #askyesnocancel
    def askyesnocancel(self,title,text):
        self.setWindowTitle(title)
        self.setText(text)
        self.setIcon(QMessageBox.Question)
        self.standard_button=QMessageBox.Yes | QMessageBox.No| QMessageBox.Cancel
        self.setStandardButtons(self.standard_button)
        return self.execute()

    #asksave
    def asksave(self,title,text):
        self.setWindowTitle(title)
        self.setText(text)
        self.setIcon(QMessageBox.Question)
        self.standard_button=QMessageBox.Save | QMessageBox.No| QMessageBox.Cancel
        self.setStandardButtons(self.standard_button)
        return self.execute()

    #asksave
    def askopen(self,title,text):
        self.setWindowTitle(title)
        self.setText(text)
        self.setIcon(QMessageBox.Question)
        self.standard_button=QMessageBox.Open | QMessageBox.No
        self.setStandardButtons(self.standard_button)
        return self.execute()

    #execute
    def execute(self):
        self.exec_()
        msg_returned=str(self.clickedButton().text()).replace('&','')
        return msg_returned

    
#Test

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QApplication, QListWidget, QVBoxLayout, QLineEdit,QPushButton



class Widget(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Msgbox")
        self.layout=QVBoxLayout()
        self.button=QPushButton("show message box")
        self.layout.addWidget(self.button)
        self.setLayout(self.layout)
        self.button.clicked.connect(self.handle_text_changed)

        #messagebox 
        self.msgbox = MessageBox()

    def handle_text_changed(self):
            #res = self.msgbox.showinfo("Title","This is a text")
            #res = self.msgbox.showerror("Title","This is a text")  #askyesnocancel
            #res = self.msgbox.askyesnocancel("Title","This is a text")
            #res = self.msgbox.askyesno("Title","This is a text")
            #res = self.msgbox.showwarning("Title","This is a text")  
            #res = self.msgbox.showerror("Title","This is a text")  
            #res = self.msgbox.asksave("Title","This is a text")  
            #res = self.msgbox.askopen("Title","This is a text")  
            res = self.msgbox.showinfo("Title","This is a text")  
            print(res)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainwindow = Widget()
    mainwindow.show()
    sys.exit(app.exec_())
    
    

`
mohammed
  • 1
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 22 '23 at 16:01