2012-03-31 11 views
9

Estuve investigando durante algún tiempo para encontrar información cómo hacer un programa multihilo usando PyQT, actualizando la GUI para mostrar los resultados.Actualización de elementos GUI en MultiThreaded PyQT

Estoy acostumbrado a aprender por ejemplo y no puedo encontrar (sí, estaba buscando por semanas) cualquier ejemplo simple de programa que usa multiprocesos para tareas tan simples como por ejemplo conectar a la lista de sitios de www (5 hilos) e imprimiendo urls procesadas con código de respuesta.

¿Alguien podría compartir el código o enviarme a un buen tutorial donde se explica dicho programa?

+0

hey, no he probado pyQt, pero he usado multiprocesamiento en pygtk. En pygtk, gobject generalmente se usa para hacer eso. Debería buscar algo similar para pyQt. – Froyo

+0

ver también http://stackoverflow.com/questions/11265812/pyside-pyqt-starting-a-cpu-intensive-thread-hangs-the-whole-application, http://stackoverflow.com/questions/16879971/example -de-la-derecha-forma-de-usar-qthread-en-pyqt, http://stackoverflow.com/questions/6783194/background-thread-with-qthread-in-pyqt o http://stackoverflow.com/questions/20752154/pyqt-connecting-a-signal-to-a-slot-to-start-a-background-operation – Trilarion

Respuesta

22

Aquí algunos ejemplos muy básicos.

Puede pasar referencias a los elementos de la GUI a los hilos y actualizarlos en el hilo.

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('%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_()) 

Nota del editor: los widgets Qt no es seguro para subprocesos y no deben ser accedidos desde cualquier hilo, pero el hilo principal (ver el Qt documentation para más detalles). La forma correcta de usar hilos es a través de señales/ranuras, como lo muestra la segunda parte de esta respuesta.


Además, puede utilizar las señales y ranuras, para separar la lógica de interfaz gráfica de usuario y la red.

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('%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_()) 
+0

Analizaré estos ejemplos. Gracias. – Nuncjo

+1

+1 por sugerir el uso de señales para separar el enhebrado de la lógica de visualización. – Whatang

+0

Los ejemplos son geniales, eso es lo que estaba buscando, pero ¿cómo limitar el número de hilos a 5 trabajando simultáneamente? – Nuncjo

Cuestiones relacionadas