Maison >développement back-end >Tutoriel Python >Comment implémenter QThreads dans PyQt pour les applications GUI réactives ?

Comment implémenter QThreads dans PyQt pour les applications GUI réactives ?

Susan Sarandon
Susan Sarandonoriginal
2024-10-19 09:55:021033parcourir

How to Implement QThreads in PyQt for Responsive GUI Applications?

Implémentation correcte de QThreads dans PyQt

Dans les applications PyQt Gui, séparer les opérations longues en threads séparés est souvent souhaitable pour maintenir la réactivité de l'interface graphique. Cependant, la réimplémentation de la méthode run est déconseillée conformément à la référence mentionnée dans la question.

Pour démontrer l'approche correcte en Python, considérons l'exemple suivant qui utilise des signaux et des emplacements pour la communication entre l'interface graphique et le thread de travail. :

  1. Créer un thread de travail : Initialisez un objet de travail et déplacez-le vers un thread séparé pour le démarrer.
  2. Connectez les signaux et les emplacements : Établissez des connexions de signal et d'emplacement entre le travailleur et les objets GUI pour les mises à jour de statut.
  3. Démarrer le thread de travail : Lorsque vous cliquez sur le bouton "Démarrer", l'interface graphique signale au thread de travail de lancer les calculs.
  4. Annuler le fil de travail : Si nécessaire, le bouton "Annuler" met fin de force au fil de travail et en crée un nouveau.

Voici le implémentation du code :

<code class="python">from PyQt4 import QtGui, QtCore
import sys
import random

class Example(QtCore.QObject):

    signalStatus = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(self.__class__, self).__init__(parent)

        self.gui = Window()
        self.createWorkerThread()
        self._connectSignals()

        self.gui.show()

    def _connectSignals(self):
        self.gui.button_cancel.clicked.connect(self.forceWorkerReset)
        self.signalStatus.connect(self.gui.updateStatus)
        self.parent().aboutToQuit.connect(self.forceWorkerQuit)

    def createWorkerThread(self):
        self.worker = WorkerObject()
        self.worker_thread = QtCore.QThread()
        self.worker.moveToThread(self.worker_thread)
        self.worker_thread.start()

        self.worker.signalStatus.connect(self.gui.updateStatus)
        self.gui.button_start.clicked.connect(self.worker.startWork)

    def forceWorkerReset(self):
        if self.worker_thread.isRunning():
            print('Terminating thread.')
            self.worker_thread.terminate()

            print('Waiting for thread termination.')
            self.worker_thread.wait()

            self.signalStatus.emit('Idle.')

            print('building new working object.')
            self.createWorkerThread()

    def forceWorkerQuit(self):
        if self.worker_thread.isRunning():
            self.worker_thread.terminate()
            self.worker_thread.wait()

class WorkerObject(QtCore.QObject):

    signalStatus = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(self.__class__, self).__init__(parent)

    @QtCore.pyqtSlot()
    def startWork(self):
        for ii in range(7):
            number = random.randint(0, 5000**ii)
            self.signalStatus.emit('Iteration: {}, Factoring: {}'.format(ii, number))
            factors = self.primeFactors(number)
            print('Number: ', number, 'Factors: ', factors)
        self.signalStatus.emit('Idle.')

    def primeFactors(self, n):
        i = 2
        factors = []
        while i * i <= n:
            if n % i:
                i += 1
            else:
                n //= i
                factors.append(i)
        if n > 1:
            factors.append(n)
        return factors

class Window(QtGui.QWidget):

    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.button_start = QtGui.QPushButton('Start', self)
        self.button_cancel = QtGui.QPushButton('Cancel', self)
        self.label_status = QtGui.QLabel('', self)

        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.button_start)
        layout.addWidget(self.button_cancel)
        layout.addWidget(self.label_status)

        self.setFixedSize(400, 200)

    @QtCore.pyqtSlot(str)
    def updateStatus(self, status):
        self.label_status.setText(status)


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    example = Example(app)
    sys.exit(app.exec_())</code>

En adhérant à cette approche, vous pouvez utiliser efficacement QThreads dans les applications PyQt, garantissant que l'interface graphique reste réactive même pendant des opérations longues.

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