0

I have a problem with my code. How to correct the code below to QMessageBox not crash program? I don't know why this problem really exists. I tried run QMessageBox in new QThread but it changed nothing.

import sys
from time import sleep
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

class Signals(QObject):
    update = pyqtSignal(int)
    enable_button = pyqtSignal(bool)

class Window(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)

        self.button = QPushButton("Run", self)
        self.button.clicked.connect(self.onButton)

        self.progress = QProgressBar(self)
        self.progress.setTextVisible(False)

        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(5, 5, 5, 5)
        self.layout.addWidget(self.button)
        self.layout.addWidget(self.progress)
        self.layout.addStretch()

        self.worker_thread = QThread()
        self.worker_thread.run =  self.worker
        self.worker_thread.should_close = False

        self.signals = Signals()
        self.signals.update.connect(self.progress.setValue)
        self.signals.enable_button.connect(self.button.setEnabled)

        self.setLayout(self.layout)
        self.show()
        self.resize(self.size().width(), 0)

    def closeEvent(self, e):
        self.worker_thread.should_close = True
        self.worker_thread.wait()

    @pyqtSlot()
    def onButton(self):
        self.button.setDisabled(True)
        self.worker_thread.start()

    def worker(self):
        for i in range(101):
            if self.worker_thread.should_close:
                break
            self.signals.update.emit(i)
            sleep(0.1)
        msgBox = QMessageBox(QMessageBox.Information, "Ok", "Done.", QMessageBox.NoButton)
        icon = QIcon()
        icon.addPixmap(QPixmap(":/favicon.ico"), QIcon.Normal, QIcon.Off)
        msgBox.setWindowIcon(icon)
        msgBox.addButton("Ok", QMessageBox.AcceptRole)
        msgBox.exec_()
        self.signals.enable_button.emit(True)

app = QApplication(sys.argv)
win = Window()
sys.exit(app.exec_())
Andy
  • 1
  • 3
  • Can you show us any crash output? Apart from that it is not clear, why you first select `QMessageBox.NoButton` and then later manually add the "Ok" button. You can use `QMessageBox::Ok` instead. – x squared Aug 01 '15 at 18:20
  • 2
    Why did you create a `QMessageBox` in a worker thread? The Qt GUI must run in the main thread. All widgets don't work in secondary threads. See [Threading Basics](http://doc.qt.io/qt-5/thread-basics.html). – nymk Aug 01 '15 at 18:37
  • Ok, I corrected issues identified by you, but it did not help. Could you provide me new idea? Please run this code in python so you can see what exactly happens, program freeze after display QMessageBox. – Andy Aug 01 '15 at 19:31
  • 2
    @Blumba. You did not correct the issues. As nymk said, you must not perform GUI operations outside the main thread. – ekhumoro Aug 01 '15 at 22:09
  • @ekhumoro so what is correct way to call QMessageBox? Look at this. http://pastebin.com/CFR0YeL2 – Andy Aug 01 '15 at 22:45
  • @Blumba. Use a custom signal. – ekhumoro Aug 01 '15 at 23:26
  • @ekhumoro custom signal? I don't know what you mean, could you give me a example how to use it? – Andy Aug 02 '15 at 22:30
  • @Blumba. Eh? You're already using them in your example (although I don't know why you put them in a separate class). – ekhumoro Aug 03 '15 at 03:01

0 Answers0