Yurkol
Yurkol

Reputation: 1482

How to pass data between threads in PyQt5?

From this PyQt - Modify GUI from another thread I learnt that "In Qt you should never attempt to directly update the GUI from outside of the GUI thread." This is why in my PyQt5 program I have a thread (Monitor), "run" method of which emits a signal to a slot (MainWindow.save_file), which in turn shows QtWidgets.QFileDialog.getSaveFileName and accepts user's input. So my question is: how can I make this MainWindow.save_file to return the user's input to a Monitor thread.

    class Communicate(QtCore.QObject):
        show_save_file = QtCore.pyqtSignal()

    class Monitor(QtCore.QThread):
        def run(self):
            self.c = Communicate()
            self.c.show_save_file.connect(MainWindow.save_file)
            self.c.show_save_file.emit()

    class MainWindow(QtWidgets.QMainWindow):

        def __init__(self):
            super().__init__()
            self.setupUi() 

        # Some other PyQt stuff here....

        def save_file(self):
            # I need this slot to return out_file_name to another thread,   Monitor
            sender = self.sender()
            out_file_name = QtWidgets.QFileDialog.getSaveFileName(self, '', '', 'flv')

Any help is greatly appreciated.

Upvotes: 2

Views: 1970

Answers (1)

user18322103
user18322103

Reputation: 61

I think it's too late for the answer, but something is better than nothing.

I have tested partial code but couldn't test the complete code due to some reasons, but it should work.

Do give it a try:

class Communicate(QtCore.QObject):
    show_save_file = QtCore.pyqtSignal()
    fileName = None

class Monitor(QtCore.QThread):
    def run(self):
        self.c = Communicate()
        self.c.show_save_file.connect(MainWindow.save_file)
        self.c.show_save_file.emit()
        
        while (Communicate.fileName == None):
            # This will make the thread wait until it gets fileName
            # If you want, add time.sleep or something to poll at
            # intervals rather than continuously polling.
            pass
        
        fileName = Communicate.fileName
        Communicate.fileName = None
        # setting this None to make sure next time it doesn't get
        # wrong fileName, if it runs again.

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super().__init__()
        self.setupUi() 

    
    def save_file(self):
        sender = self.sender()
        out_file_name = QtWidgets.QFileDialog.getSaveFileName(
            self, '', '', 'flv'
        )
        Communicate.fileName = out_file_name

Upvotes: 2

Related Questions