Все это прекрасно работает, пока я не попытаюсь подключить какой-то метод класса 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()
Технически я нашел обходной путь, позволяющий подключить сигнал к методу основного приложения, который в нем напрямую вызывает метод Box. Но я хотел бы понять, в чем проблема, чтобы улучшить кодирование pyqt.
Подробнее здесь: https://stackoverflow.com/questions/798 ... ot-emitted
Мобильная версия