ホームページ >バックエンド開発 >Python チュートリアル >複数のスレッドから PyQt GUI を効率的に更新するにはどうすればよいですか?

複数のスレッドから PyQt GUI を効率的に更新するにはどうすればよいですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-19 19:33:02377ブラウズ

How Can I Efficiently Update a PyQt GUI from Multiple Threads?

マルチスレッド 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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。