Сигнал PyQt5 между классами вызывает блокировку - PullRequest
0 голосов
/ 23 октября 2019

Я пытаюсь послать сигналы между классами, что прекрасно работает из класса HMI в класс WorkerThread, но вызывает блокировку программы или бесконечный цикл, когда WorkerThread пытается подключиться к сигналу из класса HMI.

import sys
import time

import PyQt5
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QWidget, QApplication

from Home import Ui_HomeWin     # PyQt5 Designer window

class WorkerThread(QThread):
    hmiHandlesThis = PyQt5.QtCore.pyqtSignal(str)
    def __init__(self, parent=None):
        super(WorkerThread, self).__init__(parent)
        self.counter = 0

        # this attempted connection causes a lockup
        self.HMI_Thread = HMI()     # appears to be a recursive loop
        self.HMI_Thread.updateGlobals.connect(self.update_global_widgets)

    def run(self):
        while True:
            time.sleep(0.5)
            print('Doing a bunch of other stuff: {}'.format(self.counter))
            self.counter += 1

    def build_a_command(self):
        print('building a command...')
        name = 'pbAutoMode'
        # example command
        command = name + '.setStyleSheet("QPushButton{ background-color: rgb(0, 0, 255); }")'
        self.hmiHandlesThis.emit(command)

    def update_global_widgets(self):
        print('update some global widgets')

class HMI(QWidget):
    updateGlobals = PyQt5.QtCore.pyqtSignal(name='updateGlobals')
    def __init__(self, parent=None):
        super(HMI, self).__init__(parent)

        self.HomeWin = QtWidgets.QDialog()
        self.HomeWin.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        ui = Ui_HomeWin()
        ui.setupUi(self.HomeWin)
        self.HomeWin.show()

        # this connection works
        self.workerThread = WorkerThread()
        self.workerThread.hmiHandlesThis.connect(self.on_new_command)
        self.workerThread.start()

    def on_new_command(self, command):
        print('New command is: {}'.format(command))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = HMI()
    sys.exit(app.exec_())~~~

Я попытался поместить определения сигналов в функции init , без разницы.

1 Ответ

0 голосов
/ 24 октября 2019

С помощью Денниса Дженсена я смог запустить это правильно. Я публикую здесь рабочий фрагмент в качестве примера «правильного» построения потока и передачи сигналов.

import sys
import time

import PyQt5
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QObject, QThread
from PyQt5.QtWidgets import QWidget, QApplication

from Home import Ui_HomeWin  # a PyQt5 Designer window

class WorkerThread(QObject):
    hmiHandlesThis = PyQt5.QtCore.pyqtSignal(str, str)
    def __init__(self, parent=None):
        super(WorkerThread, self).__init__(parent)
        self.counter = 0

    def processRun(self):
        while True:
            time.sleep(0.5)
            print('Doing a bunch of other stuff: {}'.format(self.counter))
            self.counter += 1

    def update_global_widgets(self):
        print('update some global widgets')

    def build_a_command(self):
        print('building a command...')
        name = 'pbAutoMode'
        # example command
        command = name + '.setStyleSheet("QPushButton{ background-color: rgb(0, 0, 255); }")'
        self.hmiHandlesThis.emit(name, command)

class HMI(QWidget):
    updateGlobals = PyQt5.QtCore.pyqtSignal(name='updateGlobals')
    def __init__(self, parent=None):
        super(HMI, self).__init__(parent)

        self.HomeWin = QtWidgets.QDialog()
        self.HomeWin.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        ui = Ui_HomeWin()
        ui.setupUi(self.HomeWin)
        self.HomeWin.show()

        self.EstablishThread()

    def EstablishThread(self):
        # Create the Object from Class
        self.Worker = WorkerThread()
        # Assign the Database Signals to Slots
        self.Worker.hmiHandlesThis.connect(self.on_new_command)

        # Create the Thread
        self.ThredHolder = QThread()
        # Move the Listener to the Thread
        self.Worker.moveToThread(self.ThredHolder)
        # Assign the Listener Starting Function to the Thread Call
        self.ThredHolder.started.connect(self.Worker.processRun)
        # Start the Thread which launches Listener.Connect( )
        self.ThredHolder.start()

    def on_new_command(self):
        print('Handling new command...')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = HMI()
    sys.exit(app.exec_())

Спасибо, Деннис!

...