Шаг 16.
Библиотека PyQt5. Знакомство с PyQt5. Многопоточные приложения. Управление циклом внутри потока (окончание)

    На этом шаге мы рассмотрим создание в потоке собственного цикла обработки сигналов.

    Каждый поток может иметь собственный цикл обработки сигналов, который запускается с помощью метода ехес_(). В этом случае потоки могут обмениваться сигналами между собой. Чтобы прервать цикл, следует вызвать слот quit() или метод exit([returnCode=0]). Рассмотрим обмен сигналами между потоками на примере.

#  -*- coding:   utf-8  -*-
from PyQt5 import QtCore, QtWidgets
class Thread1(QtCore.QThread):
    s1 = QtCore.pyqtSignal(int)
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.count = 0
    def run(self):
        self.exec_()       # Запускаем цикл обработки сигналов
    def on_start(self):
        self.count += 1
        self.s1.emit(self.count)

class Thread2(QtCore.QThread):
    s2 = QtCore.pyqtSignal(str)
    def __init__ (self, parent=None):
        QtCore.QThread.__init__(self, parent)
    def run(self):
        self.exec_()       # Запускаем цикл обработки сигналов
    def on_change(self, i):
        i += 10
        self.s2.emit("%d" % i)
        
class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.label = QtWidgets.QLabel("Нажмите кнопку")
        self.label.setAlignment(QtCore.Qt.AlignHCenter)
        self.button = QtWidgets.QPushButton("Сгенерировать сигнал")
        self.vbox = QtWidgets.QVBoxLayout()
        self.vbox.addWidget(self.label)
        self.vbox.addWidget(self.button)
        self.setLayout(self.vbox)
        self.thread1 = Thread1()
        self.thread2 = Thread2()
        self.thread1.start()
        self.thread2.start()
        self.button.clicked.connect(self.thread1.on_start)
        self.thread1.s1.connect(self.thread2.on_change)
        self.thread2.s2.connect(self.on_thread2_s2)
    def on_thread2_s2(self, s):
        self.label.setText(s)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle("Обмен сигналами между потоками")
    window.resize(300, 70)
    window.show()
    sys.exit(app.exec_())
Архив с файлом можно взять здесь.

    Результат работы приложения изображен на рисунке 1.


Рис.1. Результат работы приложения

    В этом примере мы создали классы Thread1, Thread2 и MyWindow. Первые два класса представляют собой потоки. Внутри них в методе run() вызывается метод ехес_(), который запускает цикл обработки событий. Внутри конструктора класса MyWindow производится создание надписи, кнопки и экземпляров классов Threadl и Thread2. Далее выполняется запуск сразу двух потоков.

    В следующей инструкции сигнал нажатия кнопки соединяется с методом on_start() первого потока. Внутри этого метода производится какая-либо операция (в нашем случае - увеличение значения атрибута count), а затем с помощью метода emit() генерируется сигнал s1, и в параметре передается результат выполнения метода. Сигнал s1 соединен с методом on_change() второго потока. Внутри этого метода также производится какая-либо операция, а затем генерируется сигнал s2, и передается результат выполнения метода. В свою очередь сигнал s2 соединен со слотом on_thread2_s2 объекта окна, который выводит в надпись значение, переданное с этим сигналом. Таким образом, при нажатии кнопки Сгенерировать сигнал вначале будет вызван метод on_start() из класса Thread1, затем метод on_change() из класса Thread2, а потом метод on_thread2_s2 класса MyWindow, который выведет результат выполнения на экран.

    На следующем шаге мы рассмотрим создание очереди заданий.




Предыдущий шаг Содержание Следующий шаг