Duplicate instances of emit in pyqt5 when QThread is in use

  • 2021-06-29 11:27:41
  • OfStack

When using QThread in PyQt5, be aware that all QThread objects are instantiated in the init in the class (or outside all class functions), otherwise emit may repeat signals when multiple QThreads call each other.1 Generally, the correct writing is shown below. It is OK to build the frame according to this kind of framework.


# -*- coding: utf-8 -*-
import sys
import time
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
 
 
class MainUi(QWidget):
  def __init__(self):
    super(MainUi, self).__init__()
    self.resize(400, 200)
    self.setWindowTitle('QThread Example ')
 
    #  Instantiate a multithreaded object 
    self.thread = Worker()
 
    #  Instantiate List Control and Button Control 
    self.listFile = QListWidget()
    self.btnStart = QPushButton(' start ')
    self.btn_over = QPushButton(' End ')
 
    #  Place controls in a raster layout 
    layout = QGridLayout(self)
    layout.addWidget(self.listFile, 0, 0, 1, 2)
    layout.addWidget(self.btnStart, 1, 0)
    layout.addWidget(self.btn_over, 1, 1)
 
    #  Connection of signal to slot function 
    self.btnStart.clicked.connect(self.slotStart)
    self.btn_over.clicked.connect(self.slot_btn_over)
 
    #  Establish slot connection for thread signal 
    self.thread.trigger.connect(self.slotAdd)
 
  def slotAdd(self, msg):
    print(msg)
    if int(msg) % 2 == 0:
      self.listFile.addItem(msg)
    else:
      pass
    self.thread.exit()
 
  def slotStart(self):
    self.btnStart.setEnabled(False)
    self.thread.start()
 
  def slot_btn_over(self):
    self.btnStart.setEnabled(True)
    self.thread.terminate()
    self.thread.num = 0
 
 
class Worker(QThread):
  trigger = pyqtSignal(str)
  num = 0
 
  def __init__(self):
    super(Worker, self).__init__()
 
  def run(self):
    while True:
      print('num= ', self.num)
      if self.num % 2 == 0:
        self.trigger.emit(str(50))
      elif self.num == 200:
        self.num = 0
      else:
        pass
      time.sleep(0.1)
      self.num += 1
 
 
if __name__ == '__main__':
  app = QApplication(sys.argv)
  w = MainUi()
  w.show()
  sys.exit(app.exec_())

Related articles: