0

I'm using PyQt5 and I have created a QWidgets with a QpushButton, then connecting button with a function called show_message(). When I click button the program doesn't work as expected and be crashed with the message: Process finished with exit code -1073741819 (0xC0000005) and without further error information. I have also tried using sys.excepthook (visit Logging uncaught exceptions in Python ) to log uncaught exception but the result is the same.

Here is my code:

from PyQt5.QtWidgets import QMessageBox, QApplication, QWidget
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtWidgets import QPushButton
import sys


def foo(exctype, value, tb):
    print('My Error Information')
    print('Type:', exctype)
    print('Value:', value)
    print('Traceback:', tb)

sys.excepthook = foo


def show_message(title, info, icon_path='ac_solution.ico', type_=QMessageBox.Information):
    """ show message """
    app = QApplication([])
    message_box = QMessageBox()
    message_box.setText(info)
    message_box.setWindowTitle(title)
    message_box.setWindowIcon(QtGui.QIcon(icon_path))
    message_box.setIcon(type_)
    message_box.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
    message_box.activateWindow()
    message_box.show()
    app.exec_()


app = QApplication([])
Form = QtWidgets.QWidget(flags=QtCore.Qt.WindowStaysOnTopHint)
button = QPushButton('PyQt5 button', Form)
button.setToolTip('This is an example button')
button.move(100, 70)
button.clicked.connect(lambda: show_message("hahaha", "hehehe"))
Form.show()
try:
    app.exec_()
except:
    print("exiting")

When I remove lines app = QApplication([]) and app.exec_() the program will work well, So I can guess QApplication() in show_message caused crash. But I don't know why and it makes me curious, so I need an explaination.

Pete Ythong
  • 305
  • 5
  • 13
leminhnguyen
  • 1,518
  • 2
  • 13
  • 19
  • 1
    For me it helped, when I debugged the program in PyCharm instead of running it. Then the error Messages are displayed – Uli Sotschok Aug 16 '19 at 10:35

1 Answers1

0

There are two main issues with your code. First, you are trying to run a second instance of QApplication in show_message which is what's causing the crash. Secondly, message_box is local to show_message meaning that when message_box finishes, show_message is destroyed. One way around this is to create the message box outside the function and supply it as an input parameter, e.g.

def show_message(message_box, title, info, icon_path='ac_solution.ico', type_=QMessageBox.Information):
    """ show message """
    message_box.setText(info)
    message_box.setWindowTitle(title)
    message_box.setWindowIcon(QtGui.QIcon(icon_path))
    message_box.setIcon(type_)
    message_box.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
    message_box.activateWindow()
    message_box.show()

...

button.clicked.connect(lambda x, box = QMessageBox(): show_message(box, "hahaha", "hehehe"))
Heike
  • 24,102
  • 2
  • 31
  • 45
  • Thanks you, that mean I can only create a instance of QApplication ? – leminhnguyen Aug 16 '19 at 11:33
  • 1
    @leminhnguyenHUST From the [official documentation for QApplication](https://doc.qt.io/qt-5/qapplication.html#details): "For any GUI application using Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time." Once a `QApplication` object has been created you can get access to it via `QApplication.instance()`. – Heike Aug 16 '19 at 11:49
  • @Heike The OP's `show_message` function can be fixed more simply by removing the two `app` lines and replacing `message_box.show()` with `message_box.exec_()`. I think this may be closer to what they were actually trying to achieve. – ekhumoro Aug 16 '19 at 12:16
  • @ekhumoro You are probably right. I also toyed with the idea to make `message_box` global, but I didn't want to encourage that. For a real application OP is probably better off subclassing `QWidget` and putting everything in there anyway. – Heike Aug 16 '19 at 12:26
  • @Heike Thanks you, I think your answer is the best solution for me, because I can access to current `QApplication` through `QApplication.instance()` from another module. – leminhnguyen Aug 16 '19 at 14:22