M
M
Michael2020-08-04 15:13:46
Python
Michael, 2020-08-04 15:13:46

How to send signals from a separate PyQt5 thread?

Hello!

I'm learning multithreading in QT. I'm new to multithreading.

Task : write a window that does not freeze when a network connection is established. In this case, in the event of a connection loss and other network events, there should be a certain reaction. Using this manual, I created an application to test the functionality, the code is below.

Problem : If I run a task in a separate thread, the functionality of signals and slots breaks. The network connection itself is running, but the object running in the neighboring thread does not report this in any way. The signal does not sound or is not heard.

Question : How can I catch a signal that is sent from another thread?

For example, I simplified the application code as much as possible

from PyQt5.QtNetwork import QTcpSocket
from PyQt5.QtCore import QThreadPool, QRunnable
from PyQt5.QtWidgets import QApplication


class Task(QRunnable):  # Задача, которая будет запускаться в отдельном потоке
    def __init__(self, socket):  # Передаем ссылку на объект класса QTcpSocket, через который будет установлено соединение
        super(Task, self).__init__()
        self.socket = socket  # Сохраняем ссылку на объект

    def run(self):  # Запустить обработку задачи
        self.socket.connected.emit()  # Сообщить об успешной установке соединения
        self.socket.disconnected.emit()  # Сообщить о разрыве соединения


socket = QTcpSocket()  # Создаем сокет
task = Task(socket)  # Передаем ссылку на объект сокета в задачу

socket.connected.connect(lambda: print('Connected'))  # Присоединяем обработчик к сигналу connected
socket.disconnected.connect(lambda: print('Disconnected'))  # Присоединяем обработчик к сигналу disconnected

# Ниже начинается магия

# Так работает - последовательно выводит сначала "Connected", потом "Disconnected"
#
# task.run()
#


# Так не работает - не выводит ничего - сиглалы теряются где-то по дороге.
#
thread_pool = QThreadPool()
thread_pool.start(task)
#

app = QApplication([])
app.exec_()

Answer the question

In order to leave comments, you need to log in

1 answer(s)
B
byrew rewen, 2020-08-05
@rewen

I managed to do something similar in the following way: I hung a decorator on a function that receives a signal, then the main thread remains to work in the program when the second one executes the function.
Used pyqt5 library
for example

def thread_my(my_func):
    def wrapper(*args, **kwargs):
       my_thread = threading.Thread(target=my_func, args=args, kwargs=kwargs)
       my_thread.start()
    return wrapper



    @thread_my
    def showDialog(self, true):
        print("PUST")
        cnt_list = []
        rng_contact_view_2 = self.contact_view_2.count()
        for x in range(rng_contact_view_2):
            cnt_list.append(self.contact_view_2.item(x).text())


        val_iter = 0
        for contact in cnt_list:
            val_iter += 1
            self.progress_bar(val_iter, len(cnt_list) + 1)
            bot_whatsapp().send_message(contact)
        driver.quit()
        self.progress_bar_clear()

# Вызов диалогового окна
self.btn_start.clicked.connect(self.showDialog)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question