2012-03-31 12 views
9

Stavo facendo ricerche per un po 'di tempo per trovare le informazioni come eseguire il programma multithread utilizzando PyQT, aggiornando la GUI per mostrare i risultati.Aggiornamento degli elementi della GUI in PyQT multithread

Sono abituato ad imparare dall'esempio e non riesco a trovare (sì, stavo cercando per settimane) qualsiasi semplice esempio di programma che utilizza il multithreading che svolge un compito così semplice come ad esempio collegarsi alla lista dei siti www (5 thread) e basta stampare gli URL elaborati con il codice di risposta.

Qualcuno può condividere il codice o inviarmi un buon tutorial in cui viene spiegato tale programma?

+0

hey, non ho provato pyQt, ma ho usato il multithreading in pygtk. In pygtk, il gobject è generalmente usato per farlo. Dovresti cercare qualcosa di simile a pyQt. – Froyo

+0

vedere anche http://stackoverflow.com/questions/11265812/pyside-pyqt-starting-a-cpu-intensive-thread-hangs-the-whole-application, http://stackoverflow.com/questions/16879971/example -del-right-to-use-qthread-in-pyqt, http://stackoverflow.com/questions/6783194/background-thread-with-qthread-in-pyqt o http://stackoverflow.com/questions/20752154/pyqt-connect-a-signal-to-a-slot-to-start-a-background-operation – Trilarion

risposta

22

Ecco alcuni esempi di base.

È possibile passare i riferimenti agli elementi della GUI ai thread e aggiornarli nella discussione.

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 redattore: i widget Qt non sono thread-safe e non devono essere accessibili da qualsiasi thread, ma il thread principale (vedere la Qt documentation per maggiori dettagli). Il modo corretto di usare i thread è tramite segnali/slot come mostra la seconda parte di questa risposta.


Inoltre, è possibile utilizzare segnali e slot, per separare la logica gui e la rete.

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

Analizzerò questi esempi. Grazie. – Nuncjo

+1

+1 per suggerire di utilizzare i segnali per separare la filettatura dalla logica di visualizzazione. – Whatang

+0

Gli esempi sono fantastici che è quello che stavo cercando ma come limitare il numero di thread a 5 in modo simultaneo? – Nuncjo

Problemi correlati