2012-03-31 1 views
9

私はしばらくの間、情報を見つけるために研究していたPystを使ってマルチスレッドプログラムを実行する方法、GUIを更新して結果を表示するMultiThreaded PyQTのGUI要素を更新する

私は例で学習するのに慣れています。たとえば、wwwサイト(5スレッド)のリストに接続するなどの単純なタスクを行うマルチスレッドを使用するプログラムの簡単な例を見つけることはできませんレスポンスコードで処理されたURLを表示するだけです。

誰でもコードを共有したり、そのようなプログラムが説明されている良いチュートリアルを送ってもらえますか?

+0

私はpyQtを試していませんが、私はpygtkでマルチスレッドを使用しています。 pygtkでは、一般にgobjectが使用されます。 pyQtに似たものを探すべきです。 – Froyo

+0

も参照してくださいhttp://stackoverflow.com/questions/11265812/pyside-pyqt-starting-a-cpu-intensive-thread-hangs-the-whole-application、http://stackoverflow.com/questions/16879971/example正しい方法で使用するqthread-in-pyqt、http://stackoverflow.com/questions/6783194/background-thread-with-qthread-in-pyqtまたはhttp://stackoverflow.com/questions/20752154/pyqt-connection-a-slot-to-a-background-operation – Trilarion

答えて

22

ここでは非常に基本的な例を示します。

GUIエレメントへの参照をスレッドに渡し、スレッドで更新することができます。

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

編集者注: Qtのウィジェットは、スレッドセーフではありませんし、すべてのスレッドが、メインスレッド(詳細はQt documentationを参照)からアクセスしてはなりません。スレッドを使用する正しい方法は、この回答の2番目の部分が示すように、信号/スロットを経由する方法です。


また、信号とスロットを使用して、GUIロジックとネットワークロジックを分離することもできます。

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

この例を分析します。ありがとうございました。 – Nuncjo

+1

+1信号を使用してスレッドを表示ロジックから分離することを提案します。 – Whatang

+0

例は私が探していたものですが、同時にスレッド番号を5に制限する方法は素晴らしいですか? – Nuncjo

関連する問題