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

複数のスレッドから PyQt GUI 要素を安全に更新するにはどうすればよいですか?

Barbara Streisand
リリース: 2024-12-02 01:20:10
オリジナル
1018 人が閲覧しました

How to Safely Update PyQt GUI Elements from Multiple Threads?

マルチスレッド PyQt アプリケーションの GUI 要素の更新

PyQT のマルチスレッドにより、タスクを同時に実行することでアプリケーションの応答性が向上します。ただし、固有の課題は、別のスレッドからグラフィカル ユーザー インターフェイス (GUI) を更新することです。この記事では、PyQt の非メイン スレッドから GUI 要素を安全に変更する方法の詳細な説明と例を提供します。

問題:

非メイン スレッドからの GUI 要素の変更メインスレッドが予期しない動作やクラッシュを引き起こす可能性があります。 PyQt ウィジェットはスレッドセーフではありません。つまり、メイン スレッドからのみアクセスして操作する必要があります。

シグナルとスロットを使用したスレッドセーフなアプローチ:

推奨非メインスレッドからの GUI 更新を処理するアプローチは、PyQt のシグナルとスロットのメカニズムを利用することです。シグナルはあるオブジェクトから他のオブジェクトに通知を送信しますが、スロットはそれらのシグナルに応答するメソッドです。シグナルとスロットを使用すると、更新リクエストをメイン スレッドにディスパッチして、安全かつ制御された 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_())
ログイン後にコピー

この例では、その方法を示します。マルチスレッドのダウンロード プロセスを開始し、シグナルとスロットを使用して GUI (リスト ウィジェット) を更新します。各ダウンロード スレッドはデータの準備ができたときにシグナルを発行し、メイン スレッドは「on_data_ready」スロットを通じて更新を処理します。

代替アプローチ (非推奨):

スレッドの安全性の理由から推奨されませんが、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))
ログイン後にコピー

結論:

GUI の更新を伴う PyQT でのマルチスレッド化には慎重な検討が必要です。推奨されるアプローチは、シグナルとスロットを使用して GUI 更新をメインスレッドに安全にディスパッチすることです。これにより、スレッドの安全性が確保され、アプリケーションの GUI の整合性が維持されます。

以上が複数のスレッドから PyQt GUI 要素を安全に更新するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート