ホームページ >バックエンド開発 >Python チュートリアル >複数のスレッドから PyQt GUI を効率的に更新するにはどうすればよいですか?
PyQt を使用したマルチスレッド プログラミングの世界では、共通の課題が生じます。それは、次のような要求に応じて GUI を効率的に更新する方法です。アクションは別のスレッドで実行されます。この記事の目的は、そのようなアプリケーションで応答性が高く同期された GUI 更新を実現するための実践的な例と洞察を提供することです。
1 つのアプローチは、GUI 要素への参照をスレッドに渡すことです。スレッド内で、UI コンポーネントを直接更新できます。ただし、Qt ウィジェットはスレッドセーフではないため、メイン スレッドからのみアクセスする必要があることに注意することが重要です。 PyQt ドキュメントでは、メイン スレッド以外のスレッドから 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_())
より安全で信頼性の高いスレッドから GUI を更新する方法は、シグナルとスロットを使用することです。シグナルを使用すると、スレッドからカスタム イベントを発行でき、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) # Connect our signal to our slot self.thread = DownloadThread() self.thread.data_downloaded.connect(self.on_data_ready) 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_())
シグナルとスロットを活用することで、すべての GUI が確実に更新されます。メインスレッド内で発生するため、スレッドの安全性が維持され、潜在的なエラーが防止されます。
以上が複数のスレッドから PyQt GUI を効率的に更新するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。