Сигнал PyQt5 не излучаетсяPython

Программы на Python
Ответить
Anonymous
 Сигнал PyQt5 не излучается

Сообщение Anonymous »

Я разрабатываю приложение, которое загружает данные в пользовательский класс (Box), наследуемый от QtCore.QObject, и выполняет над ним некоторую операцию, которая занимает некоторое время. Чтобы избежать зависания главного окна, я поместил все эти вычисления в отдельный поток, используя QtCore.QThreadPool.globalInstance() вместе с рабочим QtCore.QRunnable (я пытался использовать только QtCore.QThread вместе с рабочим QObject, но это не сработало, и мое приложение все еще зависало...). Когда загрузка завершена, рабочий передает ссылку на загруженные данные основному приложению, которое затем может что-то с ними делать (отображать, манипулировать...).
Все это прекрасно работает, пока я не попытаюсь подключить какой-то метод класса Box к какому-то сигналу, который излучает пользовательский интерфейс (используя простой self.button.clicked.connect(self.box.save)). Сигнал выдается, но метод никогда не вызывается, и нет никаких ошибок или чего-то еще. Все молчат. В чем проблема, я не понимаю?
Вот минимальный пример, воссоздающий проблему:

Код: Выделить всё

from PyQt5 import QtCore, QtWidgets # type: ignore[import-untyped]
import numpy as np

class Box(QtCore.QObject):

def __init__(self, data: float):
super().__init__()
self.data = data

def setData(self, data: float):
self.data = data

def save(self):
print('Box saved!')
np.savetxt('test.txt', np.array([self.data]))

class WorkerSignals(QtCore.QObject):
finished = QtCore.pyqtSignal(object)

class Worker(QtCore.QRunnable):

def __init__(self):
super().__init__()
self.signals = WorkerSignals()  # Create signals instance

def run(self):
box = Box(10.5)
self.signals.finished.emit(box)  # Serialize and emit

class MainWindow(QtWidgets.QMainWindow):

def __init__(self):
super().__init__()

self.box = None

self.edit_box = QtWidgets.QDoubleSpinBox()
self.edit_box.setDecimals(3)
self.edit_box.setValue(0.0)
self.edit_box.valueChanged.connect(self.edit_changed)

self.button_save = QtWidgets.QPushButton('Save box')
self.button_save.clicked.connect(self.verif_signal_emits)

central_widget = QtWidgets.QWidget(self)
self.setCentralWidget(central_widget)

central_layout = QtWidgets.QHBoxLayout(central_widget)
central_layout.addWidget(self.edit_box)
central_layout.addWidget(self.button_save)

self.worker = Worker()
self.worker.signals.finished.connect(self.on_data_loaded)
self.threadpool = QtCore.QThreadPool.globalInstance()
self.threadpool.start(self.worker)

def edit_changed(self, data: float):
if self.box is not None:
print('Box data before: ', self.box.data)
self.box.setData(data)
print('Box data after: ', self.box.data)
print()

def on_data_loaded(self, box: Box):
# box.moveToThread(QtCore.QThread.currentThread())
self.box = box
self.edit_box.setValue(self.box.data)
self.button_save.clicked.connect(self.box.save) # this connection does not work
# self.button_save.clicked.connect(self.save_box) # this connection works

def verif_signal_emits(self):
print('Button  clicked!')

def save_box(self):
if self.box is not None:
self.box.save()

if __name__ == '__main__':
MainEventThread = QtWidgets.QApplication([])

MainApp = MainWindow()
MainApp.show()

# This is the Qt5 way of handling it now
MainEventThread.exec()
Чтобы решить проблему, я попробовал переместить данные в основной поток, а также использовать флаг QtCore.Qt.QueuedConnection для подключения, но это не помогло.
Технически я нашел обходной путь, позволяющий подключить сигнал к методу основного приложения, который в нем напрямую вызывает метод Box. Но я хотел бы понять, в чем проблема, чтобы улучшить кодирование pyqt.

Подробнее здесь: https://stackoverflow.com/questions/798 ... ot-emitted
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»