3

I wrote a code who display in a GUI, the steps of calcul of an algorithm. For this, i use a QThread which is in charge to check the steps and display it in a GUI. This alone is working. However, the first step for the user is to select a configuration file with a QFileDialog. And at this level, Python code crashes after the openning of the QFileDialog if a file is not selected after several seconds. The crash occures when the mouse goes over the QFileDialog window openned. I quite new with the use of QThread. I started with this post Background thread with QThread in PyQt. If someone could help me understand where is my error, that would be great! Thanks!

# main_thread_simple.py
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QGridLayout, QFileDialog
import sys
import worker_simple
import os

#https://stackoverflow.com/questions/6783194/background-thread-with-qthread-in-pyqt/6789205

class Form(QWidget):

    def __init__(self):
       super(Form,self).__init__()
       self.label1 = QLabel("")
       self.label2 = QLabel("") 
       self.label3 = QLabel("") 
       self.label4 = QLabel("") 
       self.label5 = QLabel("") 
       self.label6 = QLabel("") 
       self.label7 = QLabel("") 
       self.label8 = QLabel("") 
       self.label9 = QLabel("") 
       self.label10 = QLabel("") 
       self.label11 = QLabel("") 

       fileName, _ = QFileDialog.getOpenFileName(self,"Sélectionner le fichier de configuration", filter = "(*.xlsx)")
       repertoire_fichier_configuration = os.path.basename(fileName)


       self.obj = worker_simple.Worker(repertoire_fichier_configuration)  # no parent!
       self.thread = QThread()  # no parent!

       # 2 - Connect Worker`s Signals to Form method slots to post data.
       self.obj.strReady1.connect(self.onStrReady1)
       self.obj.strReady2.connect(self.onStrReady2)

       # 3 - Move the Worker object to the Thread object
       self.obj.moveToThread(self.thread)

       # 4 - Connect Worker Signals to the Thread slots
       self.obj.finished.connect(self.thread.quit)

       # 5 - Connect Thread started signal to Worker operational slot method
       self.thread.started.connect(self.obj.Main)

       # * - Thread finished signal will close the app if you want!
#       self.thread.finished.connect(app.exit)

       # 6 - Start the thread
       self.thread.start()

       # 7 - Start the form
       self.initUI()


    def initUI(self):
        grid = QGridLayout()
        self.setLayout(grid)
        grid.addWidget(self.label1,0,0)
        grid.addWidget(self.label2,1,0)

        self.move(300, 150)
        self.setWindowTitle('outil de calcul')
        self.show()

    def onStrReady1(self, txt):
        self.label1.setText("{}".format(txt))
    def onStrReady2(self, txt):
        self.label2.setText("{}".format(txt))


app = QApplication(sys.argv)
form = Form()
sys.exit(app.exec_())
del app


# worker.py
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
import os
from PyQt5.QtWidgets import QFileDialog

class Worker(QObject):

    finished = pyqtSignal()
    strReady1 = pyqtSignal(str)
    strReady2 = pyqtSignal(str)

    def __init__(self, fichier_config, parent = None):
        super(Worker, self).__init__(parent)

        self.fichier_config = fichier_config

    @pyqtSlot()
    def Main(self): # A slot takes no params

        nom_fichier_configuration = self.fichier_config

        self.strReady1.emit('début des calculs')

        '''         code qui s'execute + appel à une fonction qui prend comme paramètre 'nom_fichier_configuration'  '''

        self.strReady2.emit('fin des calculs')    

        self.finished.emit()




SebD
  • 31
  • 3
  • Per documentation somewhere it states the following: You cannot create or access a Qt GUI object from outside the main thread (e.g. anything that subclasses QWidget or similar). So you cannot run QFileDialog from within any Thread other than the Main Thread – Dennis Jensen Aug 28 '19 at 13:17
  • 1
    The solution is simple: run the dialog in the main thread *first*, and then start the worker thread with the config file-path as a parameter. (As pointed out above, Qt does not support gui operations of any kind outside the main thread). – ekhumoro Aug 28 '19 at 14:03
  • Thanks a lot, it helped me clarified! – SebD Sep 04 '19 at 15:37
  • 1
    @DennisJensen you're statement is right. but running from main while thread is running also creates this error. just try it – greendino Oct 26 '20 at 04:58
  • @lone_coder I would have to see an MRE or MUC demonstrating this as there is so much wrong information out there on how to use QThreads or just Threads for that matter within Python it is ridiculous and I can imagine one can get all sorts of issues when trying to implement a QThread or Thread improperly. Further none of my QThread and Thread examples which I share with my students in my free online lab-class room have any issues nor have my students reported having had any issues when they have used them as guidelines for their projects. – Dennis Jensen Oct 27 '20 at 20:53

0 Answers0