web-dev-qa-db-ja.com

マルチスレッドPyQTのGUI要素の更新

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

私は例で学ぶことに慣れており、wwwサイト(5スレッド)のリストに接続して印刷処理するなどの単純なタスクを実行するマルチスレッドを使用するプログラムの簡単な例を見つけることができません(はい、数週間探していました)応答コード付きのURL。

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

19
Nuncjo

ここにいくつかの非常に基本的な例があります。

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

Editors Note:Qtウィジェットはスレッドセーフではなく、メインスレッド以外のスレッドからはアクセスできません( Qtのドキュメントを参照 =詳細については)。スレッドを使用する正しい方法は、この回答の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_())
33
reclosedev