Updating GUI elements in MultiThreaded PyQT Updating GUI elements in MultiThreaded PyQT multithreading multithreading

Updating GUI elements in MultiThreaded PyQT


Here some very basic examples.

You can pass references to GUI elements to threads, and update them in thread.

import sysimport urllib2from PyQt4 import QtCore, QtGuiclass DownloadThread(QtCore.QThread):    def __init__(self, url, list_widget):        QtCore.QThread.__init__(self)        self.url = url        self.list_widget = list_widget    def run(self):        info = urllib2.urlopen(self.url).info()        self.list_widget.addItem('%s\n%s' % (self.url, info))class MainWindow(QtGui.QWidget):    def __init__(self):        super(MainWindow, self).__init__()        self.list_widget = QtGui.QListWidget()        self.button = QtGui.QPushButton("Start")        self.button.clicked.connect(self.start_download)        layout = QtGui.QVBoxLayout()        layout.addWidget(self.button)        layout.addWidget(self.list_widget)        self.setLayout(layout)    def start_download(self):        urls = ['http://google.com', 'http://twitter.com', 'http://yandex.ru',                'http://stackoverflow.com/', 'http://www.youtube.com/']        self.threads = []        for url in urls:            downloader = DownloadThread(url, self.list_widget)            self.threads.append(downloader)            downloader.start()if __name__ == "__main__":    app = QtGui.QApplication(sys.argv)    window = MainWindow()    window.resize(640, 480)    window.show()    sys.exit(app.exec_())

Editors Note: Qt widgets are not thread safe and should not be accessed from any thread but the main thread (see the Qt documentation for more details). The correct way to use threads is via signals/slots as the second part of this answer shows.


Also, you can use signals and slots, to separate gui and network logic.

import sysimport urllib2from PyQt4 import QtCore, QtGuiclass DownloadThread(QtCore.QThread):    data_downloaded = QtCore.pyqtSignal(object)    def __init__(self, url):        QtCore.QThread.__init__(self)        self.url = url    def run(self):        info = urllib2.urlopen(self.url).info()        self.data_downloaded.emit('%s\n%s' % (self.url, info))class MainWindow(QtGui.QWidget):    def __init__(self):        super(MainWindow, self).__init__()        self.list_widget = QtGui.QListWidget()        self.button = QtGui.QPushButton("Start")        self.button.clicked.connect(self.start_download)        layout = QtGui.QVBoxLayout()        layout.addWidget(self.button)        layout.addWidget(self.list_widget)        self.setLayout(layout)    def start_download(self):        urls = ['http://google.com', 'http://twitter.com', 'http://yandex.ru',                'http://stackoverflow.com/', 'http://www.youtube.com/']        self.threads = []        for url in urls:            downloader = DownloadThread(url)            downloader.data_downloaded.connect(self.on_data_ready)            self.threads.append(downloader)            downloader.start()    def on_data_ready(self, data):        print data        self.list_widget.addItem(unicode(data))if __name__ == "__main__":    app = QtGui.QApplication(sys.argv)    window = MainWindow()    window.resize(640, 480)    window.show()    sys.exit(app.exec_())