Передача и возврат данных в класс Qthread PyQt5
Вопрос по передаче данных для расчетов и их возврате в класс QThread. В init данные передать не позволяет, вероятно, из-за наследования класса. Подскажите, пожалуйста, как это верно сделать.
Заранее спасибо!
from PyQt5 import QtCore, QtWidgets, QtSql, QtGui
from PyQt5.Qt import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.initUi()
def initUi(self):
self.btn2 = QPushButton()
self.centralWidget = QWidget(self)
self.VL = QVBoxLayout(self.centralWidget)
self.setCentralWidget(self.centralWidget)
self.gifdialog = QtWidgets.QDialog()
self.gifdialog.setFixedSize(252, 252)
self.m_label = QLabel(self.gifdialog)
self.movie = QMovie()
self.movie.setFileName(os.getcwd() + r"\mgc.gif")
self.m_label.setMovie(self.movie)
self.gifdialog.setWindowFlag(QtCore.Qt.SplashScreen)
self.thread = GifThread(self)
def connectUi(self):
self.btn2.clicked.connect(self.interpretation)
self.thread.finish_signal.connect(self.stop_gif)
def stop_gif(self):
self.movie.stop()
self.gifdialog.hide()
def interpretation(self):
#self.ai = AutoInterpretation(self.datas) #<----долгие расчеты которые переносятся в GifThread
#dots_with_data, self.support_times = self.ai.zips()
#temp_dfs = self.ai.bias_and_splitting()
self.movie.start()
self.gifdialog.show()
self.thread.start()
dots_with_data, self.support_times, temp_dfs = self.thread.results()
self.interpreted = True
class GifThread(QtCore.QThread):
finish_signal = pyqtSignal()
def __init__(self, parent=None):
QtCore.QThread.__init__(self, parent)
#self.data = data #<----- data которая нужна для расчетов, и которую надо передать в текущий класс
def run(self):
ai = AutoInterpretation(self.data) #<----расчеты, теперь в другом потоке, как сюда передать данные?
self.dwd, self.st = ai.zips()
self.td = ai.bias_and_splitting()
self.finish_signal.emit()
def results(self):
return self.dwd, self.st, self.td #еще не уверен, но пока так я собираюсь вернуть данные назад в функцию interpretation для дальнейших действий
app = QApplication(sys.argv)
MW = MainWindow()
MW.show()
sys.exit(app.exec_())
Ответы (2 шт):
Автор решения: S. Nick
→ Ссылка
я подробно расписал вам как это делается
import sys
import os
from PyQt5 import QtCore, QtWidgets, QtSql, QtGui
from PyQt5.Qt import *
class GifThread(QtCore.QThread):
finish_signal = pyqtSignal(object, object, object) # +++ (object, object, object)
# ( dwd, st, td )
def __init__(self, parent=None):
QtCore.QThread.__init__(self, parent)
self.data = None # <-- data которая нужна для расчетов, и которую получим из основного потока
def run(self):
print(self.data) # <-- data которая нужна для расчетов !!!!!
'''
ai = AutoInterpretation(self.data) #<----расчеты, теперь в другом потоке, как сюда передать данные?
sdwd, st = ai.zips()
td = ai.bias_and_splitting()
'''
# имитирую процесс длительной задачи !!!
running = 1
while running < 100:
# довольно длительно выполняющаяся часть кода
self.msleep(50)
running += 1
# в результате решения длительной задачи мы получили какие-то данные
dwd, st = [1, 2, 3], "Просто строка"
td = "Что-то еще"
self.finish_signal.emit(dwd, st, td) # <--- передать данные в основной поток !!!
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.initUi()
self.dwd = None # +++
self.st = None # +++
self.td = None # +++
def initUi(self):
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.btn2 = QPushButton("Запустить задачу")
self.btn2.clicked.connect(self.interpretation)
self.VL = QVBoxLayout(self.centralWidget)
self.VL.addWidget(self.btn2)
self.gifdialog = QtWidgets.QDialog()
self.gifdialog.setFixedSize(252, 252)
self.m_label = QLabel(self.gifdialog)
self.movie = QMovie()
self.movie.setFileName(os.getcwd() + "/img/Fo2BxBK.gif") # \mgc.gif
self.m_label.setMovie(self.movie)
self.gifdialog.setWindowFlag(QtCore.Qt.SplashScreen)
self.thread = GifThread(self)
self.thread.finish_signal.connect(self.stop_gif)
def stop_gif(self, dwd, st, td): # +++ dwd, st, td
self.movie.stop()
self.gifdialog.hide()
# используйте полученные данные где вам надо !!!
self.dwd = dwd # +++
self.st = st # +++
self.td = td # +++
print(f'''
Эти данные мы получили из дополнительного потока:
dwd = {self.dwd};
st = {self.st};
td = {self.td}.
''')
def interpretation(self):
# педположим, что в поток надо передать какой-то список фойлов
# vvvv <-- data которая нужна для расчетов, и которую надо передать в доп.поток !!!
data, _ = QtWidgets.QFileDialog.getOpenFileNames(
self, "CSV File", "", "*.csv"
)
if data: # +++ Обратите внимание, что поток запускаем если есть данные для передачи
self.thread.data = data # <-- !!! передать данные в дополнительный поток
self.movie.start()
self.gifdialog.show()
self.thread.start() # запустить дополнительный поток
if __name__ == '__main__':
app = QApplication(sys.argv)
MW = MainWindow()
MW.show()
sys.exit(app.exec_())
Автор решения: ikocs
→ Ссылка
Передавать данные можно следующим образом:
class GifThread(QtCore.QThread):
finish_signal = pyqtSignal()
def __init__(self, parent=None, data):
QtCore.QThread.__init__(self, parent)
self.data = data
Затем в методе run() их без проблем использовать.
Соответственно создание экземпляра у вас будет происходить вот так:
self.thread = GifThread(self, data)
Кроме этого, мне кажется у вас не совсем правильно реализована работа с потоками, но я могу быть не прав. Я реализую по вот этой статье.
Так такая логика:
# Создаем поток
self.thread_pool = QThreadPool()
....
# Создаем экземпляр QRunnable
class ThreadRun(QRunnable):
def __init__(self, data):
super(ThreadRun, self).__init__()
self.data = data
@pyqtSlot()
def run(self):
# Ваша логика
....
# Например, по нажатию кнопки запускаем метод
def analize_run(self):
analize = ThreadRun(self.analize)
self.thread_pool.start(analize)
Я кратко привел пример, в статье подробнее.
