Почему в консоль выводит все значения, а на надпись через одно PyQt?

Почему в консоль выводит все значения, а на label через одно?

from PyQt5 import QtCore, QtWidgets
import queue

class MyThread(QtCore.QThread):
  task_done = QtCore.pyqtSignal(int, int, name = 'taskDone')
  def __init__(self, id, queue, parent=None):
      QtCore.QThread.__init__(self, parent)
      self.id = id
      self.queue = queue
  def run(self):
      while True:
          task = self.queue.get()           # Получаем задание
          self.sleep(5)                     # Имитируем обработку
          self.task_done.emit(task, self.id) # Передаем данные обратно
          self.queue.task_done()

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.queue = queue.Queue()        # Создаем очередь
      self.threads = []
      for i in range(1, 3):             # Создаем потоки и запускаем
          thread = MyThread(i, self.queue)
          self.threads.append(thread)
          thread.task_done.connect(self.on_task_done, QtCore.Qt.QueuedConnection)
          thread.start()
      self.button.clicked.connect(self.on_add_task)
  def on_add_task(self):
      for i in range(0, 11):
          self.queue.put(i)             # Добавляем задания в очередь
  def on_task_done(self, data, id):
      self.label.setText(str(data)+", id = "+str(id))
      print(data, "- id =", id)         # Выводим обработанные данные
if __name__ == "__main__":
  import sys
  app = QtWidgets.QApplication(sys.argv)
  window = MyWindow()
  window.setWindowTitle("Использование модуля queue")
  window.resize(300, 30)
  window.show()
  sys.exit(app.exec_())

Почему в консоль выводит все значения, а на надпись через одно?


Ответы (1 шт):

Автор решения: S. Nick

В label тоже выводится все, вы просто не успеваете это заметить, т.к. две задачи выполняются параллельно и данные одной задачи очень быстро накрывают данный другой.

Чтобы вы смогли это увидеть раскомментируйте строки помеченные как #!!! и закомментируйте строки перед ними.

Вам надо сделать рассинхронизацию задач, примерно так:

QtCore.QThread.msleep(800 * task)

from PyQt5 import QtCore, QtWidgets
import queue

class MyThread(QtCore.QThread):
  task_done = QtCore.pyqtSignal(int, int, name = 'taskDone')

  def __init__(self, id, queue, parent=None):
      QtCore.QThread.__init__(self, parent)
      self.id = id
      self.queue = queue

  def run(self):
      while True:
          task = self.queue.get()             # Получаем задание

#          self.sleep(5)                      # Имитируем обработку                 # ---
          QtCore.QThread.msleep(800 * task)                                         # <<<-----<

          self.task_done.emit(task, self.id) # Передаем данные обратно
#?          self.queue.task_done()


class MyWindow(QtWidgets.QWidget):
  def __init__(self, parent=None):
      QtWidgets.QPushButton.__init__(self, parent)

      self.label = QtWidgets.QLabel("Нажмите кнопку для запуска потока")
#!!!      self.label = QtWidgets.QTextEdit("Нажмите кнопку для запуска потока")

#      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.queue = queue.Queue()        # Создаем очередь
      self.threads = []
      for i in range(1, 3):             # Создаем потоки и запускаем
          thread = MyThread(i, self.queue)
          self.threads.append(thread)
          thread.task_done.connect(self.on_task_done, QtCore.Qt.QueuedConnection)
          thread.start()
      self.button.clicked.connect(self.on_add_task)

  def on_add_task(self):
      for i in range(0, 11):
          self.queue.put(i)             # Добавляем задания в очередь

  def on_task_done(self, data, id):
      self.label.setText(str(data) + ",  id = " + str(id))
#!!!      self.label.append(str(data)+", id = "+str(id))

      print(f'on_task_done(self, data, id): {data}, id = {id}')         # Выводим обработанные данные


if __name__ == "__main__":
  import sys
  app = QtWidgets.QApplication(sys.argv)
  window = MyWindow()
  window.setWindowTitle("Использование модуля queue")
  window.resize(300, 30)
  window.show()
  sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка