Maison >développement back-end >Tutoriel Python >Comment mettre à jour en toute sécurité les éléments de l'interface graphique PyQt à partir de plusieurs threads ?

Comment mettre à jour en toute sécurité les éléments de l'interface graphique PyQt à partir de plusieurs threads ?

Barbara Streisand
Barbara Streisandoriginal
2024-12-02 01:20:10954parcourir

How to Safely Update PyQt GUI Elements from Multiple Threads?

Mise à jour des éléments de l'interface graphique dans les applications PyQt multithread

Le multithreading dans PyQT permet une réactivité accrue des applications en exécutant des tâches simultanément. Cependant, un défi inhérent consiste à mettre à jour l’interface utilisateur graphique (GUI) à partir de différents threads. Cet article fournit une explication détaillée et des exemples sur la façon de modifier en toute sécurité des éléments GUI à partir de threads non principaux dans PyQt.

Le problème :

Modifier des éléments GUI à partir de threads non principaux. les threads principaux peuvent entraîner un comportement inattendu et des plantages. Les widgets PyQt ne sont pas thread-safe, ce qui signifie qu'ils ne doivent être consultés et manipulés qu'à partir du thread principal.

Approche Thread-Safe utilisant des signaux et des emplacements :

L'approche recommandée L'approche pour gérer les mises à jour de l'interface graphique à partir des threads non principaux consiste à utiliser le mécanisme de signaux et d'emplacements de PyQt. Les signaux émettent des notifications d'un objet à d'autres, tandis que les slots sont des méthodes qui répondent à ces signaux. En utilisant des signaux et des emplacements, vous pouvez envoyer des demandes de mise à jour au thread principal, garantissant ainsi une modification sûre et contrôlée de l'interface graphique.

Exemple :

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

Cet exemple montre comment pour lancer un processus de téléchargement multithread et mettre à jour l'interface graphique (widget de liste) à l'aide de signaux et d'emplacements. Chaque fil de téléchargement émet un signal lorsque les données sont prêtes, et le fil principal gère les mises à jour via l'emplacement "on_data_ready".

Approche alternative (non recommandée) :

Bien que cela ne soit pas recommandé pour des raisons de sécurité des threads, vous pouvez également transmettre directement les références de l'interface graphique aux threads et les mettre à jour dans le thread. Cependant, cette approche nécessite une manipulation prudente et doit être évitée pour les applications critiques.

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

Conclusion :

Le multithreading dans PyQT avec les mises à jour de l'interface graphique nécessite un examen attentif. L'approche préférée consiste à utiliser des signaux et des emplacements pour distribuer en toute sécurité les mises à jour de l'interface graphique au thread principal. Cela garantit la sécurité des threads et maintient l'intégrité de l'interface graphique de votre application.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn