Сигналы и слоты Python PyQt5

У меня возникли проблемы с применением новых сигналов и слотов pyqt5 в скрипте, который предназначен состоит в том, чтобы протестировать/вызвать другую проблему, которую я пытался решить, зависание/сбой графического интерфейса... цель состоит в том, чтобы, как только эти сигналы и слоты функционируют правильно, графический интерфейс не зависал через +/- 30 секунд выполнения, и просто продолжайте считать числа до конца времен. Я предоставил пример pyqt4, хотя было бы здорово иметь решение pyqt5. Спасибо :)

from time import sleep
import os
from PyQt4 import QtCore, QtGui, uic
from PyQt4.QtGui import * 
import random
import os
import time


class Cr(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)
    def run(self):

        while True:
            rndInt = random.randint(1, 100000)
            timesleep = random.random()
            time.sleep(timesleep)
            for i in range(120):
                self.emit(QtCore.SIGNAL('host_UP'), 'foo' + str(rndInt), i)
                QtGui.QApplication.processEvents()


class Main_Window(QWidget):

    def __init__(self, *args): 
        QWidget.__init__(self, *args)
        self.relativePath = os.path.dirname(sys.argv[0])

        self.Main_Window = uic.loadUi("Main_Window.ui", self)
        self.Main_Window.show()
        self.Main_Window.move(790, 300)

        self.GU = []
        ProgressThreads = self.printThreads
        self.details_label = []
        for i in range(120):
            self.details_label.insert(i, 0)
            self.details_label[i] = QLabel(" ")
            ProgressThreads.addWidget(self.details_label[i])
            ProgressThreads.addSpacing(6)
            self.details_label[i].setText(Tools.Trim.Short('Idle', 7))
            self.GU.insert(i, Cr())
            self.GU[i].start()

        self.connect(self.GU, QtCore.SIGNAL("host_UP"), self.UpdateHost)


    def UpdateHost(self, str1, pos1):
        self.details_label[pos1].setText(str1)


class guiUpdate():
    def GUI_main(self):
        self.GUI = GUI



if __name__ == "__main__": 
    app = QApplication(sys.argv)
    guiUpdate.GUI_main.GUI = Main_Window()
    sys.exit(app.exec_())

Спасибо вам за помощь :)

ОБНОВЛЕНИЕ Приведенный ниже сценарий, надеюсь, является правильной версией PyQt5 приведенного выше сценария. Однако проблема сбоя и сообщения «не отвечает» до сих пор не решена.

from time import sleep
import os
from PyQt5 import QtCore, QtGui, uic
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QObject, pyqtSignal
import random
import os
import time
import Tools
import sys


class Cr(QtCore.QThread):
    def __init__(self, sam):
        QtCore.QThread.__init__(self)
        self.sam = sam

    def run(self):

        while True:
            rndInt = random.randint(1, 100000)
            timesleep = random.random()
            time.sleep(timesleep)
            for i in range(5):
                #time.sleep(1)

                self.sam.connect_and_emit_trigger('foo' + str(rndInt), i)
                #self.emit(QtCore.SIGNAL('host_UP'), 'foo' + str(rndInt), i)
                #QtGui.QApplication.processEvents()


class Main_Window(QWidget):

    def __init__(self, *args): 
        QWidget.__init__(self, *args)
        self.relativePath = os.path.dirname(sys.argv[0])

        self.Main_Window = uic.loadUi("Main_Window.ui", self)
        self.Main_Window.show()
        self.Main_Window.move(790, 300)

        sam = Foo()


        self.GU = []
        ProgressThreads = self.ProgressThreads
        self.details_label = []
        for i in range(5):
            self.details_label.insert(i, 0)
            self.details_label[i] = QLabel(" ")
            ProgressThreads.addWidget(self.details_label[i])
            ProgressThreads.addSpacing(6)
            self.details_label[i].setText(Tools.Trim.Short('Idle', 7))
            self.GU.insert(i, Cr(sam))
            self.GU[i].start()


class Foo(QObject):
    # Define a new signal called 'trigger' that has no arguments.
    trigger = pyqtSignal()
    def connect_and_emit_trigger(self, str, i):
        self.str = str
        self.i = i

        self.trigger.connect(self.handle_trigger)
        self.trigger.emit()

    def handle_trigger(self):
        guiUpdate.GUI_main.GUI.details_label[self.i].setText(self.str)




class guiUpdate():
    def GUI_main(self):
        self.GUI = GUI



if __name__ == "__main__": 
    app = QApplication(sys.argv)
    guiUpdate.GUI_main.GUI = Main_Window()
    sys.exit(app.exec_())

person Rhys    schedule 17.10.2013    source источник
comment
Вы можете прикрепить файл Main_Window.ui?   -  person Salvatore Avanzo    schedule 19.04.2014


Ответы (2)


Новый рекомендуемый способ использования потоков (и тот, с которым я получил наилучшие результаты) — использовать moveToThread() вместо прямого подкласса QThread. Короче говоря:

  1. напишите подкласс QObject, выполняющий реальную работу (назовем его QMyWorker). Скорее всего, это будет немного похоже на ваш существующий подкласс qthread с методом start() или run() и т. д.

  2. создать экземпляр QMyWorker без родителей

  3. создать экземпляр QThread без родителей

  4. используйте QMyWorker.moveToThread(your_thread_instance) (я иду по памяти, дважды проверьте API в документе).

  5. позвони своему QMyWorker.start()

Этот подход работал у меня для очень длинных заданий (файлы 4 ГБ и т. д.).

person Giacomo Lacava    schedule 08.06.2016

Я использовал QThreadPool, QRunnable с воркером, могу сделать больше воркеров на поток. Очень хороший пример с объяснением здесь https://martinfitzpatrick.name/article/multithreading-pyqt-applications-with-qthreadpool/

Мой PYQT5 тоже зависал, теперь я настроил его, распечатав TimeStamp.

person Marcel Giezen    schedule 23.07.2018