Updating GUI elements in MultiThreaded PyQT

Posted on

Solving problem is about exposing yourself to as many situations as possible like Updating GUI elements in MultiThreaded PyQT and practice these strategies over and over. With time, it becomes second nature and a natural way you approach any problems in general. Big or small, always start with a plan, use other strategies mentioned here till you are confident and ready to code the solution.
In this post, my aim is to share an overview the topic about Updating GUI elements in MultiThreaded PyQT, which can be followed any time. Take easy to follow this discuss.

Updating GUI elements in MultiThreaded PyQT

I was researching for some time to find information how to do multithreaded program using PyQT, updating GUI to show the results.

I’m used to learning by example and i can’t find (yes i was looking for weeks) any simple example of program using multithreading doing such simple task as for example connecting to list of www sites (5 threads) and just printing processed urls with response code.

Could anyone share code or send me to good tutorial where such program is explained ?

Asked By: Nuncjo

||

Answer #1:

Here some very basic examples.


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

import sys
import urllib2
from PyQt4 import QtCore, QtGui
class 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('%sn%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 sys
import urllib2
from PyQt4 import QtCore, QtGui
class 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('%sn%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_())
Answered By: reclosedev
The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Leave a Reply

Your email address will not be published. Required fields are marked *